Tencent/matrix · error · IllegalStateException

visit bmp instance failed, lost type def of typeId:

Error message

visit bmp instance failed, lost type def of typeId: 

What it means

While visiting a Bitmap class instance in the parsed hprof heap dump, HprofBufferShrinker resolves each field's type via Type.getType(field.typeId). If the hprof does not contain a type definition for that typeId, Type.getType returns null and the library throws IllegalStateException, because it cannot correctly read the field values (mBuffer / mRecycled) needed to determine whether the bitmap was recycled.

Solutions

  1. Re-capture the hprof from the device to replace a possibly truncated/corrupted dump.
  2. Ensure the hprof file is transferred in binary mode / fully copied before parsing.
  3. Update Matrix to a version whose HprofConstants/Type table matches the runtime that produced the dump.
  4. Wrap parsing in try-catch and fall back to skipping malformed instances.
Defensive patterns

Strategy: try-catch

Validate before calling

if (hprofFile.length() == 0) {
    throw new IOException("empty hprof: " + hprofFile);
}

Try / catch

try {
    shrinker.shrink(hprof, out);
} catch (IllegalStateException e) {
    Log.e(TAG, "hprof parse failed, falling back to raw upload", e);
}

Prevention

When it happens

Trigger: Parsing an hprof where mBmpClassInstanceFields contains a Field whose typeId has no corresponding Type definition — typically a malformed, truncated, or version-mismatched heap dump.

Common situations: Hprof produced by a newer/older ART or JVM version than the parser expects; truncated hprof transfered off-device; custom bitmap class fields with unusual type ids.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-android/src/main/java/com/tencent/matrix/resource/hproflib/HprofBufferShrinker.java:268

            super(null);
        }

        @Override
        public HprofHeapDumpVisitor visitHeapDumpRecord(int tag, int timestamp, long length) {
            return new HprofHeapDumpVisitor(null) {

                @Override
                public void visitHeapDumpInstance(ID id, int stackId, ID typeId, byte[] instanceData) {
                    try {
                        if (mBmpClassId != null && mBmpClassId.equals(typeId)) {
                            ID bufferId = null;
                            Boolean isRecycled = null;
                            final ByteArrayInputStream bais = new ByteArrayInputStream(instanceData);
                            for (Field field : mBmpClassInstanceFields) {
                                final ID fieldNameStringId = field.nameId;
                                final Type fieldType = Type.getType(field.typeId);
                                if (fieldType == null) {
                                    throw new IllegalStateException("visit bmp instance failed, lost type def of typeId: " + field.typeId);
                                }
                                if (mMBufferFieldNameStringId.equals(fieldNameStringId)) {
                                    bufferId = (ID) IOUtil.readValue(bais, fieldType, mIdSize);
                                } else if (mMRecycledFieldNameStringId.equals(fieldNameStringId)) {
                                    isRecycled = (Boolean) IOUtil.readValue(bais, fieldType, mIdSize);
                                } else if (bufferId == null || isRecycled == null) {
                                    IOUtil.skipValue(bais, fieldType, mIdSize);
                                } else {
                                    break;
                                }
                            }
                            bais.close();
                            final boolean reguardAsNotRecycledBmp = (isRecycled == null || !isRecycled);
                            if (bufferId != null && reguardAsNotRecycledBmp && !bufferId.equals(mNullBufferId)) {
                                mBmpBufferIds.add(bufferId);
                            }
                        } else if (mStringClassId != null && mStringClassId.equals(typeId)) {
                            ID strValueId = null;

View on GitHub (pinned to 3b8293bd65)