{"record":{"id":"bdfb103fc3353334","repo":"oracle/graal","slug":"invalid-java-name","errorCode":null,"errorMessage":"Invalid Java name {}","messagePattern":"Invalid Java name (.+?)","errorType":"exception","errorClass":"ParserException.ClassFormatError","httpStatus":null,"severity":"error","filePath":"espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/TypeSymbols.java","lineNumber":229,"sourceCode":"     * @return the index one past the valid type descriptor starting at {@code beginIndex}\n     * @throws ParserException.ClassFormatError if there is no valid type descriptor\n     */\n    @TruffleBoundary\n    static int skipValidTypeDescriptor(Symbol<? extends Descriptor> descriptor, int beginIndex, boolean slashes) throws ParserException.ClassFormatError {\n        if (beginIndex >= descriptor.length()) {\n            throw new ParserException.ClassFormatError(\"invalid type descriptor: \" + descriptor);\n        }\n        char ch = (char) descriptor.byteAt(beginIndex);\n        if (ch != '[' && ch != 'L') {\n            return beginIndex + 1;\n        }\n        switch (ch) {\n            case 'L': {\n                final int endIndex = skipClassName(descriptor, beginIndex + 1, slashes ? '/' : '.');\n                if (endIndex > beginIndex + 1 && endIndex < descriptor.length() && descriptor.byteAt(endIndex) == ';') {\n                    return endIndex + 1;\n                }\n                throw new ParserException.ClassFormatError(\"Invalid Java name \" + descriptor.subSequence(beginIndex));\n            }\n            case '[': {\n                // compute the number of dimensions\n                int index = beginIndex;\n                while (index < descriptor.length() && descriptor.byteAt(index) == '[') {\n                    index++;\n                }\n                final int dimensions = index - beginIndex;\n                if (dimensions > 255) {\n                    throw new ParserException.ClassFormatError(\"Array with more than 255 dimensions \" + descriptor.subSequence(beginIndex));\n                }\n                return skipValidTypeDescriptor(descriptor, index, slashes);\n            }\n        }\n        throw new ParserException.ClassFormatError(\"Invalid type descriptor \" + descriptor.subSequence(beginIndex));\n    }\n\n    /**","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/TypeSymbols.java#L211-L247","documentation":"When a descriptor starts with 'L', skipValidTypeDescriptor requires a class name of at least one character terminated by ';' within the descriptor. If skipClassName returns an empty name, hits the end, or the terminating ';' is missing, it throws ParserException.ClassFormatError 'Invalid Java name <rest-of-descriptor>'.","triggerScenarios":"Descriptors like 'Ljava/lang/String' (no ';'), 'L;' (empty class name), or a name that runs to end-of-string without termination; also unbalanced slicing where the ';' fell outside the subSequence handed to the parser.","commonSituations":"Hand-assembled descriptors in code generators forgetting the ';'; strings built from Class.getName() (which uses '.' not '/') without replacing dots with slashes; truncation of the final character during string manipulation.","solutions":["End every reference descriptor with ';' and use '/' separators: 'Ljava/lang/String;'","Build descriptors from Class.getName().replace('.', '/') inside 'L...;' rather than string templates","Add a regex pre-check for reference descriptors: ^L[^;.\\[]+;$"],"exampleFix":"// before\nString desc = \"L\" + cls.getName().replace('.', '/') ; // missing ';'\n\n// after\nString desc = \"L\" + cls.getName().replace('.', '/') + \";\";","handlingStrategy":"validation","validationCode":"if (!desc.matches(\"L[^;.\\[]+;\")) throw new IllegalArgumentException(\"Bad reference descriptor (need L<name>; with '/' separators): \" + desc);","typeGuard":"static boolean isReferenceDescriptor(String d) { return d != null && d.matches(\"L[^;.\\[]+;\"); }","tryCatchPattern":"catch (ParserException.ClassFormatError e) { point at the missing ';' or empty name in the reported descriptor }","preventionTips":["Always terminate reference descriptors with ';' and use '/' package separators","Derive descriptors via Class.getName().replace('.', '/') instead of templates"],"tags":["espresso","classfile","descriptor","parsing"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}