oracle/graal · error · IllegalArgumentException

Unknown tag %d

Error message

Unknown tag %d

What it means

BinaryInput.readValue dispatches on a one-byte type tag written by BinaryOutput.writeValue. Tags cover boxed primitives (BOOLEAN, BYTE, CHAR, INT, LONG, FLOAT, DOUBLE) and STRING; anything else throws IllegalArgumentException(String.format("Unknown tag %d", tag)). An unknown tag means the stream is misaligned or produced by an incompatible protocol version.

Source

Thrown at compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/BinaryInput.java:359

                return readBoolean();
            case BYTE:
                return readByte();
            case SHORT:
                return readShort();
            case CHAR:
                return readChar();
            case INT:
                return readInt();
            case LONG:
                return readLong();
            case FLOAT:
                return readFloat();
            case DOUBLE:
                return readDouble();
            case STRING:
                return readUTF();
            default:
                throw new IllegalArgumentException(String.format("Unknown tag %d", tag));
        }
    }

    /**
     * Reads {@code len} bytes into a boolean array starting at offset {@code off}.
     *
     * @throws IndexOutOfBoundsException if there are not enough bytes to read
     */
    public final void read(boolean[] b, int off, int len) {
        ensureBufferSize(len);
        read(tempEncodingByteBuffer, 0, len);
        int limit = off + len;
        for (int i = off, j = 0; i < limit; i++) {
            b[i] = tempEncodingByteBuffer[j++] != 0;
        }
    }

    /**

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Ensure the writing and reading sides come from the same GraalVM/libgraal build.
  2. Audit the sequence of read calls to confirm each consumes exactly the bytes its write counterpart produced.
  3. Do not interleave manual buffer reads with readValue on the same stream.
  4. If a tag value >= some new constant appears, upgrade the reader side to the version that defines it.
Defensive patterns

Strategy: validation

Validate before calling

// Before readValue, sanity-check the tag byte
int tag = in.readByte(); // or peek if available
if (tag != BOOLEAN && tag != BYTE && tag != CHAR && tag != INT && tag != LONG && tag != FLOAT && tag != DOUBLE && tag != STRING) {
    throw new IllegalArgumentException("stream misaligned; unexpected tag " + tag);
}

Try / catch

try {
    Object v = in.readValue();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unknown tag")) {
        // abort the record: version mismatch or desync; renegotiate format version
    }
}

Prevention

When it happens

Trigger: Calling readValue when the input position sits on a byte that is not a valid type tag — e.g. after a previous read consumed too few/many bytes, or when the writer used a newer BinaryOutput with extra tags the reader's BinaryInput does not know.

Common situations: GraalVM version mismatch between the process embedding libgraal and the libgraal image; a manual read of the raw stream; a corrupted native buffer.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/48293b44cf4048e5. Report an issue: GitHub.