didi/DoKit · error · IllegalStateException
Negative size: " + bitmap
Error message
Negative size: " + bitmap
What it means
Utils.getBitmapBytes(Bitmap) computes a bitmap's byte size — getByteCount() on API 12+, otherwise rowBytes * height — and throws IllegalStateException if the result is negative. A negative value means the arithmetic overflowed int (rowBytes * height exceeded 2^31) or the bitmap is in an invalid state; the library treats it as an unrecoverable accounting error because cache sizing and stats depend on it.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/Utils.java:116
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
private static final int WEBP_FILE_HEADER_SIZE = 12;
private static final String WEBP_FILE_HEADER_RIFF = "RIFF";
private static final String WEBP_FILE_HEADER_WEBP = "WEBP";
private Utils() {
// No instances.
}
static int getBitmapBytes(Bitmap bitmap) {
int result;
if (SDK_INT >= HONEYCOMB_MR1) {
result = BitmapHoneycombMR1.getByteCount(bitmap);
} else {
result = bitmap.getRowBytes() * bitmap.getHeight();
}
if (result < 0) {
throw new IllegalStateException("Negative size: " + bitmap);
}
return result;
}
static <T> T checkNotNull(T value, String message) {
if (value == null) {
throw new NullPointerException(message);
}
return value;
}
static void checkNotMain() {
if (isMain()) {
throw new IllegalStateException("Method call should not happen from the main thread.");
}
}
static void checkMain() {View on GitHub (pinned to 626827cddb)
Solutions
- Downsample large sources: use .resize(targetW, targetH).onlyScaleDown() on the request, or BitmapFactory.Options.inSampleSize for manual decoding.
- Target view-sized dimensions rather than native image dimensions for all loads.
- If it reproduces only on ancient devices, gate huge-image features by device memory class (ActivityManager.getMemoryClass()).
Example fix
// before
picasso.load(hugePhotoUrl).into(imageView); // full-res decode, overflows byte count
// after
picasso.load(hugePhotoUrl)
.resize(imageView.getMaxWidth(), imageView.getMaxHeight())
.onlyScaleDown()
.centerInside()
.into(imageView); Defensive patterns
Strategy: validation
Validate before calling
// Bound the decode size before loading int maxDim = context.getResources().getDisplayMetrics().widthPixels; picasso.load(url).resize(maxDim, maxDim).onlyScaleDown().centerInside().into(iv);
Try / catch
Not applicable — the throw indicates corrupted size accounting; prevent by bounding bitmap dimensions.
Prevention
- Never decode huge sources at native resolution; always resize/onlyScaleDown.
- Watch memory class on old devices; cap image sizes accordingly.
- Treat any occurrence as an out-of-memory-adjacent bug and fix sizing.
When it happens
Trigger: On pre-Honeycomb MR1 devices, loading or creating a bitmap whose rowBytes * height overflows Integer.MAX_VALUE (over ~2GB, e.g. decoding a huge photo without downsampling); extremely rarely, a bitmap whose dimensions report nonsense values.
Common situations: Decoding a very large camera image at full resolution into memory with no inSampleSize; old-device (API < 12) code paths in legacy builds; OOM-adjacent situations where a bitmap larger than 2GB is attempted.
Related errors
- Target callback must not recycle bitmap!
- Transformation " + transformation.key() + " crashed with exc
- Transformation " + transformation.key() + " returned null af
- Transformation " + transformation.key() + " returned input B
- Transformation <transformation.key()> mutated input Bitmap b
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/7cb454c8185603c0.
Report an issue: GitHub.