Tencent/matrix · error · IllegalArgumentException
acceptHeapDumpRecord loop with unknown tag " + heapDumpTag…
Error message
acceptHeapDumpRecord loop with unknown tag " + heapDumpTag + " with " + mStreamIn.available() + " bytes possibly remaining
What it means
HprofReader.acceptHeapDumpRecord() switches on each heap dump record's tag. When the tag does not match any known HprofConstants record type, the parser throws IllegalArgumentException reporting the unknown tag and remaining bytes, because the record layout is unknown and the stream position can no longer be advanced safely.
Solutions
- Upgrade Matrix so HprofConstants/acceptHeapDumpRecord covers the record tags of the runtime that produced the dump.
- Capture the hprof with the standard 'am dumpheap' of the target device and re-check the dump format version in the header.
- Fix any earlier parse error (e.g. bad idSize) that may have desynchronized the byte stream.
- Catch IllegalArgumentException around accept() and treat the dump as unsupported rather than crashing.
Defensive patterns
Strategy: try-catch
Validate before calling
String version = readHprofVersionHeader(file);
if (!SUPPORTED_VERSIONS.contains(version)) {
throw new IOException("unsupported hprof version: " + version);
} Try / catch
try {
hprofReader.accept(visitor);
} catch (IllegalArgumentException e) {
Log.e(TAG, "unknown heap dump tag; hprof likely from newer runtime", e);
} Prevention
- Keep Matrix updated for new ART hprof record types.
- Capture dumps with the device's own 'am dumpheap'.
- Treat repeated unknown-tag errors as a format-version mismatch, not a data bug.
When it happens
Trigger: Parsing an hprof whose heap dump section contains a tag outside the parser's known set — dumps written by a newer ART/JVM HPROF version, or a stream already desynchronized from earlier mis-parsing.
Common situations: Hprof from a newer Android/JDK version than the parser supports (e.g. Android 14+ ART adding record types); parsing the 1.0.2 variant with a 1.0.1 parser; a prior bad idSize silently desynchronizing the stream.
Related errors
- accept class failed, lost type def of typeId:
- accept primitive array failed, lost type def of typeId:
- Can only rewind one step!
- Couldn't read string!
- Couldn't read number!
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/91e11f91700123cc.
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/HprofReader.java:222
length -= mIdSize;
break;
case HprofConstants.HEAPDUMP_ROOT_REFERENCE_CLEANUP:
hdv.visitHeapDumpBasicObj(heapDumpTag, IOUtil.readID(mStreamIn, mIdSize));
length -= mIdSize;
break;
case HprofConstants.HEAPDUMP_ROOT_VM_INTERNAL:
hdv.visitHeapDumpBasicObj(heapDumpTag, IOUtil.readID(mStreamIn, mIdSize));
length -= mIdSize;
break;
case HprofConstants.HEAPDUMP_ROOT_JNI_MONITOR:
length -= acceptJniMonitor(hdv);
break;
case HprofConstants.HEAPDUMP_ROOT_UNREACHABLE:
hdv.visitHeapDumpBasicObj(heapDumpTag, IOUtil.readID(mStreamIn, mIdSize));
length -= mIdSize;
break;
default:
throw new IllegalArgumentException(
"acceptHeapDumpRecord loop with unknown tag " + heapDumpTag
+ " with " + mStreamIn.available()
+ " bytes possibly remaining");
}
}
hdv.visitEnd();
}
private void acceptUnconcernedRecord(int tag, int timestamp, long length, HprofVisitor hv) throws IOException {
final byte[] data = new byte[(int) length];
IOUtil.readFully(mStreamIn, data, 0, length);
hv.visitUnconcernedRecord(tag, timestamp, length, data);
}
private int acceptHeapDumpInfo(HprofHeapDumpVisitor hdv) throws IOException {
final int heapId = IOUtil.readBEInt(mStreamIn);
final ID heapNameId = IOUtil.readID(mStreamIn, mIdSize);
hdv.visitHeapDumpInfo(heapId, heapNameId);View on GitHub (pinned to 3b8293bd65)