nostra13/Android-Universal-Image-Loader · error · IllegalArgumentException

memoryCacheSize must be a positive number

Error message

memoryCacheSize must be a positive number

What it means

ImageLoaderConfiguration.Builder.memoryCacheSize(int) validates that the byte budget for the default LruMemoryCache is strictly positive, throwing IllegalArgumentException otherwise (the check ultimately matches LruMemoryCache's own constructor guard). A non-positive size would make the LRU evict every entry immediately or never stabilize, so it is rejected at configuration time. Using this method also switches the memory cache to LruMemoryCache and warns if you had set a custom memoryCache().

Source

Thrown at library/src/main/java/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java:359

		public Builder tasksProcessingOrder(QueueProcessingType tasksProcessingType) {
			if (taskExecutor != null || taskExecutorForCachedImages != null) {
				L.w(WARNING_OVERLAP_EXECUTOR);
			}

			this.tasksProcessingType = tasksProcessingType;
			return this;
		}

		/**
		 * Sets maximum memory cache size for {@link android.graphics.Bitmap bitmaps} (in bytes).<br />
		 * Default value - 1/8 of available app memory.<br />
		 * <b>NOTE:</b> If you use this method then
		 * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as
		 * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of
		 * {@link MemoryCache}.
		 */
		public Builder memoryCacheSize(int memoryCacheSize) {
			if (memoryCacheSize <= 0) throw new IllegalArgumentException("memoryCacheSize must be a positive number");

			if (memoryCache != null) {
				L.w(WARNING_OVERLAP_MEMORY_CACHE);
			}

			this.memoryCacheSize = memoryCacheSize;
			return this;
		}

		/**
		 * Sets maximum memory cache size (in percent of available app memory) for {@link android.graphics.Bitmap
		 * bitmaps}.<br />
		 * Default value - 1/8 of available app memory.<br />
		 * <b>NOTE:</b> If you use this method then
		 * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as
		 * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of
		 * {@link MemoryCache}.
		 */

View on GitHub (pinned to ba33ec64d0)

Solutions

  1. Pass an explicit positive byte value: memoryCacheSize(32 * 1024 * 1024)
  2. For relative sizing use memoryCacheSizePercentage(...) instead of manual math
  3. Clamp computed sizes: Math.max(1, computed)

Example fix

// before
int sizeMb = readRemoteConfig("mem_cache_mb"); // 0 when field missing
builder.memoryCacheSize(sizeMb); // may also be 0 bytes even when non-zero check passes

// after
int sizeMb = Math.max(8, readRemoteConfig("mem_cache_mb"));
builder.memoryCacheSize(sizeMb * 1024 * 1024);
Defensive patterns

Strategy: validation

Validate before calling

int bytes = Math.max(1, computedCacheBytes);
builder.memoryCacheSize(bytes);

Prevention

When it happens

Trigger: memoryCacheSize(0) or a negative value in the builder; computing the size from an expression that yields 0 on the current device (empty free-memory calculation, integer underflow, a 0 multiplier).

Common situations: Device-dependent size math returning 0 on low-RAM devices or emulators; passing a megabyte constant without multiplying by 1024*1024 while testing with value 0; config generated from a remote JSON where the field was absent and defaulted to 0.

Related errors


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