Index: src/uk/me/parabola/imgfmt/MapFailedException.java
===================================================================
--- src/uk/me/parabola/imgfmt/MapFailedException.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/MapFailedException.java	(working copy)
@@ -12,8 +12,6 @@
  */
 package uk.me.parabola.imgfmt;
 
-import uk.me.parabola.log.Logger;
-
 /**
  * Used for cases where the current map has failed to compile, but the error
  * is expected to be specific to the map (eg it is too big etc).  When this
@@ -26,10 +24,10 @@
  * @author Steve Ratcliffe
  */
 public class MapFailedException extends RuntimeException {
-	private static final Logger log = Logger.getLogger(MapFailedException.class);
 
 	/**
-	 * Constructs a new runtime exception with the specified detail message.
+	 * Constructs a new runtime exception with the calling method name
+	 * appended to the detail message.
 	 * The cause is not initialized, and may subsequently be initialized by a
 	 * call to {@link #initCause}.
 	 *
@@ -37,13 +35,13 @@
 	 *                later retrieval by the {@link #getMessage()} method.
 	 */
 	public MapFailedException(String message) {
-		super(message);
-		log(message);
+		super(buildMessage(message));
 	}
 
 	/**
-	 * Constructs a new runtime exception with the specified detail message and
-	 * cause.  <p>Note that the detail message associated with
+	 * Constructs a new runtime exception with the calling method name
+	 * appended to the detail message and includes the cause.
+	 * <p>Note that the detail message associated with
 	 * <code>cause</code> is <i>not</i> automatically incorporated in
 	 * this runtime exception's detail message.
 	 *
@@ -53,23 +51,32 @@
 	 *                {@link #getCause()} method).  (A <tt>null</tt> value is
 	 *                permitted, and indicates that the cause is nonexistent or
 	 *                unknown.)
-	 * @since 1.4
 	 */
 	public MapFailedException(String message, Throwable cause) {
-		super(message, cause);
-		log(message);
+		super(buildMessage(message), cause);
 	}
 	
-	private static void log(String message){
+	/**
+	 * Constructs a new runtime exception without appending the calling method
+	 * name to the detail message. The calling method can be appended by the
+	 * derived class if required.
+	 */
+	protected MapFailedException(String message, boolean ignored) {
+		super(message);
+	}
+
+	/**
+	 * Appends the calling method name to the supplied message.
+	 */
+	protected static String buildMessage(String message) {
 		String thrownBy = "";
 		try{
 			StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
 			int callerPosInStack = 3; 
 			String[] caller = stackTraceElements[callerPosInStack].getClassName().split("\\.");
-			thrownBy = "(thrown in " + caller[caller.length-1]+ "." +stackTraceElements[callerPosInStack].getMethodName() + "()) ";
+			thrownBy = " (thrown in " + caller[caller.length-1]+ "." +stackTraceElements[callerPosInStack].getMethodName() + "())";
 		} catch(Exception e){
-			log.info(e);
 		}
-		log.error(thrownBy + message);
+		return message + thrownBy;
 	}
 }
\ No newline at end of file
Index: src/uk/me/parabola/imgfmt/MapTooBigException.java
===================================================================
--- src/uk/me/parabola/imgfmt/MapTooBigException.java	(nonexistent)
+++ src/uk/me/parabola/imgfmt/MapTooBigException.java	(working copy)
@@ -0,0 +1,36 @@
+package uk.me.parabola.imgfmt;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MapTooBigException extends MapFailedException {
+	protected final long maxAllowedSize;
+
+	public MapTooBigException(long maxSize) {
+		this(maxSize,
+				getSection() == null ? "The map or tile is too big." : "The " + getSection() + " section of the map or tile is too big.",
+				"Try splitting the map into smaller tiles or reducing the amount of information included in the map.");
+	}
+	
+	public MapTooBigException(long maxSize, String message, String suggestion) {
+		super(message + " The maximum size is " + maxSize + " bytes. " + suggestion, false);
+		maxAllowedSize = maxSize;
+	}
+	
+	public long getMaxAllowedSize() {
+		return maxAllowedSize;
+	}
+
+	private static String getSection() {
+		StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+		final List<String> sectionNames = Arrays.asList("DEM", "LBL", "Mdr", "NET", "NOD", "RGN", "TRE");
+		for (int i = 2; i < stackTraceElements.length; i++) {
+			StackTraceElement ste = stackTraceElements[i];
+			String className = ste.getClassName();
+			className = className.substring(className.lastIndexOf('.') + 1);
+			if (className.length() >= 3 && sectionNames.contains(className.substring(0, 3)))
+				return className;
+		}
+		return null;
+	}
+}
Index: src/uk/me/parabola/imgfmt/app/BufferedImgFileWriter.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/BufferedImgFileWriter.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/BufferedImgFileWriter.java	(working copy)
@@ -20,7 +20,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
-import uk.me.parabola.imgfmt.MapFailedException;
+import uk.me.parabola.imgfmt.MapTooBigException;
 import uk.me.parabola.imgfmt.Sized;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.imgfmt.sys.FileLink;
@@ -269,12 +269,11 @@
 		if (needed > (bufferSize - GUARD_SIZE)) {
 			while(needed > (bufferSize - GUARD_SIZE))
 				bufferSize += GROW_SIZE;
+			if (bufferSize > maxAllowedSize && needed < (maxAllowedSize - GUARD_SIZE)) {
+				bufferSize = (int) maxAllowedSize; 
+			}
 			if (bufferSize > maxAllowedSize) {
-				// Previous message was confusing people, although it is difficult to come
-				// up with something that is strictly true in all situations.
-				throw new MapFailedException(
-						"There is not enough room in a single garmin map for all the input data." +
-								" The .osm file should be split into smaller pieces first.");
+				throw new MapTooBigException(maxAllowedSize);
 			}
 			ByteBuffer newb = ByteBuffer.allocate(bufferSize);
 			newb.order(ByteOrder.LITTLE_ENDIAN);
Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 4605)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -375,8 +375,7 @@
 			log.info("DEM file calculation for", map.getFilename(), "took", (t2 - t1), "ms");
 			demFile.write();
 		} catch (MapFailedException e) {
-			log.error("exception while creating DEM file", e.getMessage());
-			throw new MapFailedException("DEM"); 
+			throw new MapFailedException("Error creating DEM File. " + e.getMessage()); 
 		}
 	}
 
@@ -501,7 +500,7 @@
 		}
 
 	}
-	
+
 	private void processRoads(Map map, MapDataSource src) {
 		LBLFile lbl = map.getLblFile();
 		MapPoint searchPoint = new MapPoint();
Index: src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java	(revision 4605)
+++ src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java	(working copy)
@@ -22,6 +22,7 @@
 import uk.me.parabola.imgfmt.FileNotWritableException;
 import uk.me.parabola.imgfmt.FileSystemParam;
 import uk.me.parabola.imgfmt.MapFailedException;
+import uk.me.parabola.imgfmt.MapTooBigException;
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
@@ -192,9 +193,17 @@
 			mb.makeMap(map, overviewSource);
 			map.close();
 		} catch (FileExistsException e) {
+			log.error("Could not create overview map");
 			throw new ExitException("Could not create overview map", e);
 		} catch (FileNotWritableException e) {
+			log.error("Could not write to overview map");
 			throw new ExitException("Could not write to overview map", e);
+		} catch (MapTooBigException e) {
+			e = new MapTooBigException(e.getMaxAllowedSize(),
+					"The overview map is too big.",
+					"Try reducing the highest overview resolution or reducing the amount of information included in the overview.");
+			log.error(e.getMessage());
+			throw e;
 		}
 	}
 
Index: src/uk/me/parabola/mkgmap/main/Main.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/Main.java	(revision 4605)
+++ src/uk/me/parabola/mkgmap/main/Main.java	(working copy)
@@ -151,7 +151,7 @@
 				System.err.println("Try using the Java -Xmx option to increase the available heap memory.");
 		} catch (MapFailedException e) {
 			// one of the combiners failed
-			e.printStackTrace();
+			log.error(e.getMessage());
 			++numExitExceptions;
 		} catch (ExitException e) {
 			++numExitExceptions;
@@ -560,16 +560,16 @@
 						else
 							throw e;
 					}
-				} catch (OutOfMemoryError | ExitException e) {
-					throw e;
+				} catch (InterruptedException e) {
+					throw new ExitException("Exiting due to interruption");
 				} catch (MapFailedException mfe) {
 					numMapFailedExceptions++;
 					setProgramRC(-1);
-				} catch (Throwable t) {
-					t.printStackTrace();
 					if (!args.getProperties().getProperty("keep-going", false)) {
 						throw new ExitException("Exiting - if you want to carry on regardless, use the --keep-going option");
 					}
+				} catch (Exception e) {
+					throw new ExitException(e.getMessage());
 				}
 			}
 		}
Index: src/uk/me/parabola/mkgmap/main/MapMaker.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/MapMaker.java	(revision 4605)
+++ src/uk/me/parabola/mkgmap/main/MapMaker.java	(working copy)
@@ -120,10 +120,16 @@
 			map.close();
 			return outName;
 		} catch (FileExistsException e) {
+			log.error("File exists already");
 			throw new MapFailedException("File exists already", e);
 		} catch (FileNotWritableException e) {
+			log.error("Could not create or write to file");
 			throw new MapFailedException("Could not create or write to file", e);
 		}
+		catch (MapFailedException e) {
+			log.error(e.getMessage()); // make sure the filename is logged
+			throw e;
+		}
 	}
 
 	/**
