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;
@@ -41,6 +41,7 @@
 	private static final int GUARD_SIZE = KBYTE;
 
 	private final ImgChannel chan;
+	private final String subfile;
 
 	private ByteBuffer buf = ByteBuffer.allocate(INIT_SIZE);
 	private int bufferSize = INIT_SIZE;
@@ -55,8 +56,9 @@
 	// The maximum allowed file size.
 	private long maxAllowedSize = 0xffffff;
 
-	public BufferedImgFileWriter(ImgChannel chan) {
+	public BufferedImgFileWriter(ImgChannel chan, String subfile) {
 		this.chan = chan;
+		this.subfile = subfile;
 		buf.order(ByteOrder.LITTLE_ENDIAN);
 		if (chan instanceof FileLink) {
 			((FileLink) chan).link(this, this);
@@ -270,11 +272,9 @@
 			while(needed > (bufferSize - GUARD_SIZE))
 				bufferSize += GROW_SIZE;
 			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,
+						"The " + subfile + " 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.");
 			}
 			ByteBuffer newb = ByteBuffer.allocate(bufferSize);
 			newb.order(ByteOrder.LITTLE_ENDIAN);
Index: src/uk/me/parabola/imgfmt/app/dem/DEMFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/dem/DEMFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/dem/DEMFile.java	(working copy)
@@ -15,6 +15,7 @@
 
 import java.util.List;
 
+import uk.me.parabola.imgfmt.ExitException;
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
@@ -46,7 +47,7 @@
 		setHeader(demHeader);
 
 		if (write) {
-			setWriter(new BufferedImgFileWriter(chan));
+			setWriter(new BufferedImgFileWriter(chan, "DEM"));
 			position(DEMHeader.HEADER_LEN);
 		} else {
 			setReader(new BufferedImgFileReader(chan));
@@ -98,6 +99,8 @@
 			}
 			// last 4 bits of distance should be 0
 			distance = ((distance + 8) / 16) * 16;
+			if (distance == 0)
+				throw new ExitException("DEM distance is zero");
 
 			int xTop = top;
 			int xLeft = left;
Index: src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java	(working copy)
@@ -66,7 +66,7 @@
 		lblHeader.setOffsetMultiplier(OFFSET_MULTIPLIER);
 		setHeader(lblHeader);
 
-		setWriter(new BufferedImgFileWriter(chan));
+		setWriter(new BufferedImgFileWriter(chan, "LBL"));
 
 		position((long) LBLHeader.HEADER_LEN + lblHeader.getSortDescriptionLength());
 
Index: src/uk/me/parabola/imgfmt/app/mdr/Mdr1MapIndex.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/mdr/Mdr1MapIndex.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/mdr/Mdr1MapIndex.java	(working copy)
@@ -25,7 +25,7 @@
  */
 public class Mdr1MapIndex {
 	private final Mdr1SubHeader subHeader = new Mdr1SubHeader();
-	private final BufferedImgFileWriter subWriter = new BufferedImgFileWriter(null);
+	private final BufferedImgFileWriter subWriter = new BufferedImgFileWriter(null, "MDR");
 
 	private int pointerSize;
 
Index: src/uk/me/parabola/imgfmt/app/net/NETFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/NETFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/net/NETFile.java	(working copy)
@@ -51,7 +51,7 @@
 
 	public NETFile(ImgChannel chan) {
 		setHeader(netHeader);
-		setWriter(new BufferedImgFileWriter(chan));
+		setWriter(new BufferedImgFileWriter(chan, "NET"));
 		position(NETHeader.HEADER_LEN);
 	}
 
Index: src/uk/me/parabola/imgfmt/app/net/NODFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/NODFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/net/NODFile.java	(working copy)
@@ -59,7 +59,7 @@
 	public NODFile(ImgChannel chan, boolean write) {
 		setHeader(nodHeader);
 		if (write) {
-			setWriter(new BufferedImgFileWriter(chan));
+			setWriter(new BufferedImgFileWriter(chan, "NOD"));
 			position(NODHeader.HEADER_LEN);
 		} else {
 			setReader(new BufferedImgFileReader(chan));
Index: src/uk/me/parabola/imgfmt/app/srt/SRTFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/srt/SRTFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/srt/SRTFile.java	(working copy)
@@ -40,7 +40,7 @@
 	private final List<Integer> srt8Starts = new ArrayList<>();
 
 	public SRTFile(ImgChannel chan) {
-		BufferedImgFileWriter fileWriter = new BufferedImgFileWriter(chan);
+		BufferedImgFileWriter fileWriter = new BufferedImgFileWriter(chan, "SRT");
 		fileWriter.setMaxSize(Long.MAX_VALUE);
 		setWriter(fileWriter);
 	}
Index: src/uk/me/parabola/imgfmt/app/trergn/RGNFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/trergn/RGNFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/trergn/RGNFile.java	(working copy)
@@ -57,7 +57,7 @@
 	public RGNFile(ImgChannel chan) {
 		setHeader(header);
 
-		setWriter(new BufferedImgFileWriter(chan));
+		setWriter(new BufferedImgFileWriter(chan, "RGN"));
 
 		// Position at the start of the writable area.
 		position(HEADER_LEN);
Index: src/uk/me/parabola/imgfmt/app/trergn/TREFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/trergn/TREFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/trergn/TREFile.java	(working copy)
@@ -64,7 +64,7 @@
 
 	public TREFile(ImgChannel chan) {
 		setHeader(header);
-		setWriter(new BufferedImgFileWriter(chan));
+		setWriter(new BufferedImgFileWriter(chan, "TRE"));
 
 		// Position at the start of the writable area.
 		position(header.getHeaderLength());
Index: src/uk/me/parabola/imgfmt/app/typ/TYPFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/typ/TYPFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/app/typ/TYPFile.java	(working copy)
@@ -55,7 +55,7 @@
 
 	public TYPFile(ImgChannel chan) {
 		setHeader(header);
-		setWriter(new BufferedImgFileWriter(chan));
+		setWriter(new BufferedImgFileWriter(chan, "TYP"));
 		position(TYPHeader.HEADER_LEN);
 	}
 
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,14 @@
+package uk.me.parabola.imgfmt;
+
+public class MapTooBigException extends MapFailedException {
+	protected final long maxAllowedSize;
+
+	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;
+	}
+}
Index: src/uk/me/parabola/imgfmt/mps/MpsFile.java
===================================================================
--- src/uk/me/parabola/imgfmt/mps/MpsFile.java	(revision 4605)
+++ src/uk/me/parabola/imgfmt/mps/MpsFile.java	(working copy)
@@ -46,7 +46,7 @@
 
 	public MpsFile(ImgChannel chan) {
 		assert chan instanceof FileNode;
-		writer = new BufferedImgFileWriter(chan);
+		writer = new BufferedImgFileWriter(chan, "MPS");
 	}
 
 	public void sync() throws IOException {
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)
@@ -36,6 +36,7 @@
 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 import uk.me.parabola.imgfmt.ExitException;
 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;
@@ -374,9 +375,10 @@
 			long t2 = System.currentTimeMillis();
 			log.info("DEM file calculation for", map.getFilename(), "took", (t2 - t1), "ms");
 			demFile.write();
+		} catch (MapTooBigException e) {
+			throw new MapTooBigException(e.getMaxAllowedSize(), "The DEM section of the map or tile is too big.", "Try increasing the DEM distance."); 
 		} 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 +503,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;
@@ -195,6 +196,10 @@
 			throw new ExitException("Could not create overview map", e);
 		} catch (FileNotWritableException e) {
 			throw new ExitException("Could not write to overview map", e);
+		} catch (MapTooBigException e) {
+			throw 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.");
 		}
 	}
 
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)
@@ -149,12 +149,9 @@
 				System.err.println("Try using the mkgmap --max-jobs option with a value less than " + mm.maxJobs  + " to reduce the memory requirement, or use the Java -Xmx option to increase the available heap memory.");
 			else
 				System.err.println("Try using the Java -Xmx option to increase the available heap memory.");
-		} catch (MapFailedException e) {
+		} catch (MapFailedException | ExitException e) {
 			// one of the combiners failed
-			e.printStackTrace();
 			++numExitExceptions;
-		} catch (ExitException e) {
-			++numExitExceptions;
 			String message = e.getMessage();
 			Throwable cause = e.getCause();
 			while (cause != null) {
@@ -560,16 +557,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;
+		}
 	}
 
 	/**
