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

  1. Only put a pair after checking both: if (uri != null && bitmap != null) cache.put(...)
  2. Handle decode failure upstream (onLoadingFailed) instead of writing a null placeholder
  3. 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

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


AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14). Data as JSON: /api/errors/c676da8211456643. Report an issue: GitHub.