Tencent/matrix · error · IOException

bad idSize:

Error message

bad idSize: 

What it means

HprofReader.acceptHeader() reads the idSize field from the hprof header. Every object id in the dump is sized by this value, so the reader validates it is a sane positive int (< Integer.MAX_VALUE >> 1) before proceeding; otherwise it throws IOException("bad idSize: ..."), because continuing would corrupt all subsequent ID reads.

Solutions

  1. Verify the file starts with the hprof magic header 'JAVA PROFILE 1.0.1' / 'JAVA PROFILE 1.0.2' before parsing.
  2. Re-transfer/re-capture the hprof; check file size and that the copy completed.
  3. Decompress .hprof.gz files before handing them to HprofReader.
  4. Wrap accept() in try-catch for IOException and surface a user-friendly 'invalid hprof file' error.

Example fix

// before
new HprofReader(new BufferedInputStream(new FileInputStream(file))).accept(visitor);
// after
try (FileInputStream fis = new FileInputStream(file)) {
    byte[] magic = new byte[17];
    if (fis.read(magic) < 17 || !new String(magic, 0, 11).equals("JAVA PROFILE")) {
        throw new IOException("not a valid hprof file: " + file);
    }
    new HprofReader(new BufferedInputStream(fis)).accept(visitor);
}
Defensive patterns

Strategy: validation

Validate before calling

try (FileInputStream fis = new FileInputStream(file)) {
    byte[] head = new byte[18];
    if (fis.read(head) < 18 || !new String(head, 0, 11, "US-ASCII").equals("JAVA PROFILE")) {
        throw new IOException("not a valid hprof: " + file);
    }
}

Try / catch

try {
    hprofReader.accept(visitor);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("bad idSize")) {
        Log.e(TAG, "invalid or corrupt hprof file", e);
    }
}

Prevention

When it happens

Trigger: Opening a stream with HprofReader.accept() where the bytes at the idSize position of the hprof header decode to <= 0 or >= Integer.MAX_VALUE/2 — i.e. the input is not a valid hprof or the header is misaligned.

Common situations: Passing a non-hprof file (log, HTML error page, empty file) to the parser; truncated download where the header read consumes wrong bytes; wrong file path opened; gzipped hprof not decompressed first.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/cb7f4bcd76e2d608. 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:50

public class HprofReader {
    private final InputStream mStreamIn;
    private int mIdSize = 0;

    public HprofReader(InputStream in) {
        mStreamIn = in;
    }

    public void accept(HprofVisitor hv) throws IOException {
        acceptHeader(hv);
        acceptRecord(hv);
        hv.visitEnd();
    }

    private void acceptHeader(HprofVisitor hv) throws IOException {
        final String text = IOUtil.readNullTerminatedString(mStreamIn);
        final int idSize = IOUtil.readBEInt(mStreamIn);
        if (idSize <= 0 || idSize >= (Integer.MAX_VALUE >> 1)) {
            throw new IOException("bad idSize: " + idSize);
        }
        final long timestamp = IOUtil.readBELong(mStreamIn);
        mIdSize = idSize;
        hv.visitHeader(text, idSize, timestamp);
    }

    private void acceptRecord(HprofVisitor hv) throws IOException {
        try {
            while (true) {
                final int tag = mStreamIn.read();
                final int timestamp = IOUtil.readBEInt(mStreamIn);
                final long length = IOUtil.readBEInt(mStreamIn) & 0x00000000FFFFFFFFL;
                switch (tag) {
                    case HprofConstants.RECORD_TAG_STRING:
                        acceptStringRecord(timestamp, length, hv);
                        break;
                    case HprofConstants.RECORD_TAG_LOAD_CLASS:
                        acceptLoadClassRecord(timestamp, length, hv);

View on GitHub (pinned to 3b8293bd65)