oracle/graal · error · ParserException.ClassFormatError

invalid descriptor: {}

Error message

invalid descriptor: {}

What it means

TypeSymbols.parse handles single-character (primitive) descriptors via JavaKind.fromPrimitiveOrVoidTypeChar. When that single character is not a valid primitive/void letter ('Z C F D B S I J V'), the failure is wrapped as ParserException.ClassFormatError 'invalid descriptor: <desc>' — i.e. the descriptor is one character long but meaningless, such as 'X', 'A', or lowercase 'i'.

Source

Thrown at espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/TypeSymbols.java:201

        return kind.getType();
    }

    /**
     * Parses a valid Java type descriptor.
     *
     * @param descriptor the raw signature from which to create a Java type descriptor
     * @param beginIndex the index within the string from which to start parsing
     * @param slashes specifies if package components in {@code string} are separated by {@code '/'}
     *            or {@code '.'}
     * @throws ParserException.ClassFormatError if the type descriptor is not valid
     */
    Symbol<Type> parse(Symbol<? extends Descriptor> descriptor, int beginIndex, boolean slashes) throws ParserException.ClassFormatError {
        int endIndex = skipValidTypeDescriptor(descriptor, beginIndex, slashes);
        if (endIndex == beginIndex + 1) {
            try {
                return forPrimitive(JavaKind.fromPrimitiveOrVoidTypeChar((char) descriptor.byteAt(beginIndex)));
            } catch (IllegalStateException e) {
                throw new ParserException.ClassFormatError("invalid descriptor: " + descriptor);
            }
        }
        return symbols.getOrCreate(descriptor.subSequence(beginIndex, endIndex));
    }

    /**
     * Verifies that a valid type descriptor is at {@code beginIndex} in {@code type}.
     *
     * @param slashes specifies if package components are separated by {@code '/'} or {@code '.'}
     * @return the index one past the valid type descriptor starting at {@code beginIndex}
     * @throws ParserException.ClassFormatError if there is no valid type descriptor
     */
    @TruffleBoundary
    static int skipValidTypeDescriptor(Symbol<? extends Descriptor> descriptor, int beginIndex, boolean slashes) throws ParserException.ClassFormatError {
        if (beginIndex >= descriptor.length()) {
            throw new ParserException.ClassFormatError("invalid type descriptor: " + descriptor);
        }
        char ch = (char) descriptor.byteAt(beginIndex);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use the canonical JVM descriptor letters: Z=boolean C=char F=float D=double B=byte S=short I=int J=long V=void, references 'L...;' arrays '[...'
  2. Add a descriptor validator in your generator before emitting class files so errors surface at generation time with file context
  3. Check for case errors — all primitive letters are uppercase

Example fix

// before
Symbol<Type> t = typeSymbols.parse(symbolOf("i"), 0, true); // lowercase

// after
Symbol<Type> t = typeSymbols.parse(symbolOf("I"), 0, true); // JVM int descriptor
Defensive patterns

Strategy: validation

Validate before calling

if (desc.length() == 1 && "ZCFDBSIJV".indexOf(desc.charAt(0)) < 0) throw new IllegalArgumentException("Bad primitive descriptor: " + desc);

Type guard

static boolean isValidPrimitiveDescriptor(String d) { return d.length() == 1 && "ZCFDBSIJV".indexOf(d.charAt(0)) >= 0; }

Try / catch

catch (ParserException.ClassFormatError e) { include the descriptor and generating class in the error }

Prevention

When it happens

Trigger: A one-character type descriptor that is not a JVM primitive letter — typos like 'i' instead of 'I', 'x', 'P'; or a truncated multi-char descriptor that happened to be cut to its first bad character.

Common situations: Hand-written or templated descriptor strings in bytecode generators; case errors (JVM letters are uppercase); descriptors copied from human-readable documentation ('int') instead of JVM form ('I').

Related errors


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