Tencent/matrix · error · RuntimeException

Unable to obtained scaled bitmap's dimensions

Error message

Unable to obtained scaled bitmap's dimensions

What it means

Matrix Resource Canary fails to read the width/height of a bitmap stored in an hprof heap dump after it has downsized the bitmap data. The decoder first re-encodes/downsizes the bitmap buffer, then calls dataProvider.getDimension(); if that returns null the scaled bitmap has no readable dimensions, so analysis cannot proceed and it throws a RuntimeException.

Solutions

  1. Verify the hprof file is complete and uncorrupted (re-capture the dump).
  2. Check that the bitmap was not recycled before the heap dump was taken; skip analysis for recycled bitmaps.
  3. Increase or disable the downsizing threshold (bitmap downsize config) so the original buffer is decoded directly.
  4. Update Matrix to the latest version; bitmap decoding across Android bitmap representations (Bitmap.Config, hardware bitmaps) has been patched repeatedly.
  5. Wrap the analysis step in try-catch and treat this bitmap as unanalyzable instead of failing the whole report.

Example fix

// before
size = dataProvider.getDimension();
if (size == null) {
    throw new RuntimeException("Unable to obtained scaled bitmap's dimensions");
}
// after
size = dataProvider.getDimension();
if (size == null) {
    // fall back to decoding without downscaling
    size = decodeDimensionsWithoutDownsize(dataProvider);
    if (size == null) {
        return null; // skip this bitmap rather than aborting analysis
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before analysis
if (hprofFile == null || hprofFile.length() == 0) throw new IllegalArgumentException("empty hprof");

Try / catch

try { size = dataProvider.getDimension(); } catch (RuntimeException e) { log.warn("bitmap unreadable, skipping", e); return null; }

Prevention

When it happens

Trigger: getBitmap is called during hprof bitmap analysis when the bitmap buffer could be downsized but dataProvider.getDimension() returns null — i.e. the heap dump data for the bitmap is truncated, corrupted, or the bitmap's internal width/height fields could not be decoded from the scaled buffer.

Common situations: Analyzing hprof dumps from devices where the bitmap was too large and the downsizing step produced an unreadable buffer; corrupted or truncated hprof files; bitmaps whose mWidth/mHeight fields were recycled/cleared before the dump was taken.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/2bf5ae2b88542210. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-analyzer-cli/src/main/java/com/tencent/matrix/resource/analyzer/utils/BitmapDecoder.java:90

        if (bitmapExtractor == null) {
            throw new RuntimeException("Unsupported bitmap configuration: " + config);
        }

        Dimension size = dataProvider.getDimension();
        if (size == null) {
            throw new RuntimeException("Unable to determine image dimensions.");
        }

        // if the image is rather large, then scale it down
        if (size.width > MAX_DIMENSION || size.height > MAX_DIMENSION) {
            boolean couldDownsize = dataProvider.downsizeBitmap(size);
            if (!couldDownsize) {
                throw new RuntimeException("Unable to create scaled bitmap");
            }

            size = dataProvider.getDimension();
            if (size == null) {
                throw new RuntimeException("Unable to obtained scaled bitmap's dimensions");
            }
        }

        return bitmapExtractor.getImage(size.width, size.height, dataProvider.getPixelBytes(size));
    }

    private static class ARGB8888_BitmapExtractor implements BitmapExtractor {
        @Override
        public BufferedImage getImage(int width, int height, byte[] rgba) {
            @SuppressWarnings("UndesirableClassUsage")
            BufferedImage bufferedImage = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

            for (int y = 0; y < height; y++) {
                int stride = y * width;
                for (int x = 0; x < width; x++) {
                    int i = (stride + x) * 4;
                    long rgb = 0;

View on GitHub (pinned to 3b8293bd65)