diff --git .gitignore .gitignore
new file mode 100644
index 0000000..2384283
--- /dev/null
+++ .gitignore
@@ -0,0 +1,3 @@
+/bin/
+/build/
+/dist/
diff --git src/org/openstreetmap/josm/data/cache/ICachedLoaderListener.java src/org/openstreetmap/josm/data/cache/ICachedLoaderListener.java
index 32fa35a..fe26c09 100644
--- src/org/openstreetmap/josm/data/cache/ICachedLoaderListener.java
+++ src/org/openstreetmap/josm/data/cache/ICachedLoaderListener.java
@@ -2,12 +2,25 @@
 package org.openstreetmap.josm.data.cache;
 
 public interface ICachedLoaderListener {
+
+    /**
+     * Result of download
+     *
+     */
+    enum LoadResult {
+        SUCCESS,
+        FAILURE,
+        REJECTED
+    }
     /**
-     * Will be called when K object was successfully downloaded
-     * 
+     * Will be called when K object processed. The result might be:
+     * LoadResult.SUCCESS when object was fetched
+     * LoadResult.FAILURE when there was a failure during download
+     * LoadResult.REJECTED when job was rejected because of full queue
+     *
      * @param data
-     * @param success
+     * @param result
      */
-    public void loadingFinished(CacheEntry data, boolean success);
+    public void loadingFinished(CacheEntry data, LoadResult result);
 
 }
diff --git src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
index d636de4..478004b 100644
--- src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
+++ src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
@@ -26,6 +26,7 @@ import java.util.logging.Logger;
 import org.apache.commons.jcs.access.behavior.ICacheAccess;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.openstreetmap.gui.jmapviewer.FeatureAdapter;
+import org.openstreetmap.josm.data.cache.ICachedLoaderListener.LoadResult;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
 
 /**
@@ -151,7 +152,7 @@ public abstract class JCSCachedTileLoaderJob<K, V extends CacheEntry> implements
             if (cacheElement != null && isCacheElementValid() && (isObjectLoadable())) {
                 // we got something in cache, and it's valid, so lets return it
                 log.log(Level.FINE, "JCS - Returning object from cache: {0}", getCacheKey());
-                finishLoading(true);
+                finishLoading(LoadResult.SUCCESS);
                 return;
             }
             // object not in cache, so submit work to separate thread
@@ -161,7 +162,7 @@ public abstract class JCSCachedTileLoaderJob<K, V extends CacheEntry> implements
             } catch (RejectedExecutionException e) {
                 // queue was full, try again later
                 log.log(Level.FINE, "JCS - rejected job for: {0}", getCacheKey());
-                finishLoading(false);
+                finishLoading(LoadResult.REJECTED);
             }
         }
     }
@@ -205,16 +206,16 @@ public abstract class JCSCachedTileLoaderJob<K, V extends CacheEntry> implements
         try {
             // try to load object from remote resource
             if (loadObject()) {
-                finishLoading(true);
+                finishLoading(LoadResult.SUCCESS);
             } else {
                 // if loading failed - check if we can return stale entry
                 if (isObjectLoadable()) {
                     // try to get stale entry in cache
-                    finishLoading(true);
+                    finishLoading(LoadResult.SUCCESS);
                     log.log(Level.FINE, "JCS - found stale object in cache: {0}", getUrl());
                 } else {
                     // failed completely
-                    finishLoading(false);
+                    finishLoading(LoadResult.FAILURE);
                 }
             }
         } finally {
@@ -223,7 +224,7 @@ public abstract class JCSCachedTileLoaderJob<K, V extends CacheEntry> implements
     }
 
 
-    private void finishLoading(boolean success) {
+    private void finishLoading(LoadResult result) {
         Set<ICachedLoaderListener> listeners = null;
         synchronized (inProgress) {
             listeners = inProgress.remove(getUrl().toString());
@@ -234,13 +235,13 @@ public abstract class JCSCachedTileLoaderJob<K, V extends CacheEntry> implements
         }
         try {
             for (ICachedLoaderListener l: listeners) {
-                l.loadingFinished(cacheData, success);
+                l.loadingFinished(cacheData, result);
             }
         } catch (Exception e) {
             log.log(Level.WARNING, "JCS - Error while loading object from cache: {0}; {1}", new Object[]{e.getMessage(), getUrl()});
             log.log(Level.FINE, "Stacktrace", e);
             for (ICachedLoaderListener l: listeners) {
-                l.loadingFinished(cacheData, false);
+                l.loadingFinished(cacheData, LoadResult.FAILURE);
             }
 
         }
diff --git src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
index cb7754f..44e8467 100644
--- src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
+++ src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
@@ -132,17 +132,23 @@ public class TMSCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, Buffe
         return false;
     }
 
+    private boolean isNoTileAtZoom() {
+        return attributes != null && attributes.isNoTileAtZoom();
+    }
+
     @Override
     protected boolean cacheAsEmpty() {
-        if (attributes != null && attributes.isNoTileAtZoom()) {
-            // do not remove file - keep the information, that there is no tile, for further requests
-            // the code above will check, if this information is still valid
+        return isNoTileAtZoom();
+    }
+
+    private boolean handleNoTileAtZoom() {
+        if (isNoTileAtZoom()) {
             log.log(Level.FINE, "JCS TMS - Tile valid, but no file, as no tiles at this level {0}", tile);
             tile.setError("No tile at this zoom level");
             tile.putValue("tile-info", "no-tile");
             return true;
         }
-        return false; // as there is no other cache to cache the Tile, also cache other empty requests
+        return false;
     }
 
     @Override
@@ -156,11 +162,25 @@ public class TMSCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, Buffe
     }
 
     @Override
-    public void loadingFinished(CacheEntry object, boolean success) {
+    public void loadingFinished(CacheEntry object, LoadResult result) {
         try {
-            loadTile(object, success);
+            tile.finishLoading(); // whatever happened set that loading has finished
+            switch(result){
+            case FAILURE:
+                tile.setError("Problem loading tile");
+            case SUCCESS:
+                handleNoTileAtZoom();
+                if (object != null) {
+                    byte[] content = object.getContent();
+                    if (content != null && content.length > 0) {
+                        tile.loadImage(new ByteArrayInputStream(content));
+                    }
+                }
+            case REJECTED:
+                // do not set anything here, leave waiting sign
+            }
             if (listener != null) {
-                listener.tileLoadingFinished(tile, success);
+                listener.tileLoadingFinished(tile, result.equals(LoadResult.SUCCESS));
             }
         } catch (IOException e) {
             log.log(Level.WARNING, "JCS TMS - error loading object for tile {0}: {1}", new Object[] {tile.getKey(), e.getMessage()});
@@ -180,7 +200,14 @@ public class TMSCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, Buffe
         BufferedImageCacheEntry data = get();
         if (isObjectLoadable()) {
             try {
-                loadTile(data);
+                if (data != null && data.getImage() != null) {
+                    tile.setImage(data.getImage());
+                    tile.finishLoading();
+                }
+                if (isNoTileAtZoom()) {
+                    handleNoTileAtZoom();
+                    tile.finishLoading();
+                }
                 return tile;
             } catch (IOException e) {
                 log.log(Level.WARNING, "JCS TMS - error loading object for tile {0}: {1}", new Object[] {tile.getKey(), e.getMessage()});
@@ -188,31 +215,7 @@ public class TMSCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, Buffe
             }
 
         } else {
-            return null;
-        }
-    }
-
-    // loads tile when calling back from cache
-    private void loadTile(CacheEntry object, boolean success) throws IOException {
-        tile.finishLoading();
-        if (object != null) {
-            byte[] content = object.getContent();
-            if (content != null && content.length > 0) {
-                tile.loadImage(new ByteArrayInputStream(content));
-            }
-        }
-        if (!success) {
-            tile.setError("Problem loading tile");
-        }
-    }
-
-    // loads tile when geting stright from cache
-    private void loadTile(BufferedImageCacheEntry object) throws IOException {
-        tile.finishLoading();
-        if (cacheAsEmpty() || object != null) { // if cache as empty object, do not try to load image
-            if (object.getImage() != null) {
-                tile.setImage(object.getImage());
-            }
+            return tile;
         }
     }
 
