oracle/graal · error · ParserException.ClassFormatError
Unexpected tag: ${tag}
Error message
Unexpected tag: ${tag} What it means
A ClassFormatError (ParserException) thrown while walking a constant pool during ConstantPoolPatcher's first pass: an entry whose tag byte does not match any known JVM constant tag (Utf8, Integer, Long, Float, Double, Class, String, ... MethodHandle) hits the default branch. The pool bytes are structurally corrupt, so the class file is rejected as malformed.
Source
Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ConstantPoolPatcher.java:106
stream.readS4();
break;
case FLOAT:
stream.readFloat();
break;
case LONG:
stream.readS8();
++i;
break;
case DOUBLE:
stream.readDouble();
++i;
break;
case METHODHANDLE:
stream.readU1();
stream.readU2();
break;
default:
throw new ParserException.ClassFormatError("Unexpected tag: " + tag);
}
i++;
}
}
private static boolean isDirectAnonymousInnerClass(ByteSequence outer, ByteSequence inner) {
if (!inner.contentStartsWith(outer) || inner.length() < outer.length() + 2) {
return false;
}
int i = outer.length();
if (inner.byteAt(i++) != '$') {
return false;
}
do {
if (!isDecimalDigit(inner.byteAt(i++))) {
return false;
}
} while (i < inner.length());View on GitHub (pinned to a66e9ccd1d)
Solutions
- Verify the class file with a standard tool (javap -v, or a JVM load of the same class) — if it also fails, the class is genuinely corrupt.
- Rebuild/re-download the jar or regenerate the class with a recent, compatible bytecode tool.
- If agent-based patching is involved, disable it and re-test to see whether the patcher mangles the pool.
- Check the class file major version is supported by this Espresso version.
Defensive patterns
Strategy: validation
Validate before calling
// before loading untrusted class bytes
byte[] bytes = ...;
if (bytes.length < 10 || bytes[6] > SUPPORTED_MAJOR_VERSION) {
throw new ClassFormatException("suspicious class file");
} Try / catch
try {
context.getEnv().parseClass(bytes);
} catch (ParserException.ClassFormatError e) {
// reject the input; log the offending resource so the corrupt artifact can be replaced
} Prevention
- Validate class-file checksums/signatures when loading untrusted classes.
- Keep bytecode-generation tools (ASM etc.) updated and version-compatible with the guest classes.
- Do not run two class transformers that both rewrite constant pools on the same classes.
When it happens
Trigger: Loading a class whose constant pool contains an unknown/reserved tag byte (not 1-15 or 17-19); truncated or shifted pool data so the parser reads a non-tag byte as a tag; a class file corrupted on disk, in a jar, or by an earlier patching step that desynchronized the pool offsets.
Common situations: Corrupted jar/agent instrumentation that rewrites constant pools incorrectly; class files produced by broken bytecode tools or modified by an outdated patcher; truncated downloads; classes from a newer class-file version using tags this parser predates.
Related errors
- Invalid constant pool tag: %s
- No ClassConstant at constant pool index ${cpi}
- InvalidClassFormat
- Cannot bind label to negative position %d
- Out of scratch registers: %s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/7eea98336026f7a2.
Report an issue: GitHub.