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

  1. 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.
  2. Rebuild/re-download the jar or regenerate the class with a recent, compatible bytecode tool.
  3. If agent-based patching is involved, disable it and re-test to see whether the patcher mangles the pool.
  4. 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

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


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