nostra13/Android-Universal-Image-Loader · error · NullPointerException
key == null || value == null
Error message
key == null || value == null
What it means
LruMemoryCache.put(String, Bitmap) throws NullPointerException when either the key or the value is null. The cache's size accounting (sizeOf on both the inserted and the replaced bitmap) requires non-null entries, and caching null would corrupt the LRU bookkeeping. In normal use keys are generated URIs and values are decoded bitmaps, so this indicates a caller bug.
Source
Thrown at library/src/main/java/com/nostra13/universalimageloader/cache/memory/impl/LruMemoryCache.java:58
* Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head
* of the queue. This returns null if a Bitmap is not cached.
*/
@Override
public final Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
return map.get(key);
}
}
/** Caches {@code Bitmap} for {@code key}. The Bitmap is moved to the head of the queue. */
@Override
public final boolean put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
synchronized (this) {
size += sizeOf(key, value);
Bitmap previous = map.put(key, value);
if (previous != null) {
size -= sizeOf(key, previous);
}
}
trimToSize(maxSize);
return true;
}
/**
* Remove the eldest entries until the total of remaining entries is at or below the requested size.
*
* @param maxSize the maximum size of the cache before returning. May be -1 to evict even 0-sized elements.View on GitHub (pinned to ba33ec64d0)
Solutions
- Only put a pair after checking both: if (uri != null && bitmap != null) cache.put(...)
- Handle decode failure upstream (onLoadingFailed) instead of writing a null placeholder
- Use ImageLoader's own pipeline (displayImage/loadImage), which never invokes put with nulls
Example fix
// before
Bitmap decoded = BitmapFactory.decodeStream(is);
ImageLoader.getInstance().getMemoryCache().put(uri, decoded); // decoded == null -> NPE
// after
Bitmap decoded = BitmapFactory.decodeStream(is);
if (uri != null && decoded != null) {
ImageLoader.getInstance().getMemoryCache().put(uri, decoded);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (uri != null && bitmap != null && !bitmap.isRecycled()) {
ImageLoader.getInstance().getMemoryCache().put(uri, bitmap);
} Type guard
static boolean isCacheableEntry(String key, Bitmap value) {
return key != null && value != null && !value.isRecycled();
} Prevention
- Check decode results for null before caching them
- Do not pre-warm the cache from background decoders without null checks
- Never recycle a bitmap that is still inside the cache
When it happens
Trigger: Calling memoryCache.put(uri, null) after a decode failure; put(null, bitmap) with an unset URI; custom post-processors or custom caches forwarding null bitmaps into put().
Common situations: Custom code that pre-warms the cache and passes a bitmap variable that decode returned null for on OOM-corrupted streams; adapter code where the model's image URL field is null/optional.
Related errors
- key == null
- Wrong arguments were passed to displayImage() method (ImageV
- maxSize <= 0
- {className}.sizeOf() is reporting inconsistent results!
- bitmapConfig can't be null
AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14).
Data as JSON: /api/errors/c676da8211456643.
Report an issue: GitHub.