{"record":{"id":"f25a2bc0cb7a1525","repo":"oracle/graal","slug":"class-name-classname-does-not-match-pattern","errorCode":null,"errorMessage":"Class name \"${className}\" does not match pattern ${QUALIFIED_CLASS_NAME_RE}","messagePattern":"Class name \"(.+?)\" does not match pattern (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java","lineNumber":212,"sourceCode":"\n    /**\n     * Regular expression for a qualified class name that assumes package names start with lowercase\n     * and non-package components start with uppercase.\n     */\n    private static final Pattern QUALIFIED_CLASS_NAME_RE = Pattern.compile(\"(?:[a-z]\\\\w*\\\\.)+([A-Z].*)\");\n\n    /**\n     * Gets the non-package component of a qualified class name.\n     *\n     * @throws IllegalArgumentException if {@code className} does not match\n     *             {@link #QUALIFIED_CLASS_NAME_RE}\n     */\n    public static String getSimpleName(String className) {\n        Matcher m = QUALIFIED_CLASS_NAME_RE.matcher(className);\n        if (m.matches()) {\n            return m.group(1);\n        }\n        throw new IllegalArgumentException(\"Class name \\\"\" + className + \"\\\" does not match pattern \" + QUALIFIED_CLASS_NAME_RE);\n    }\n\n    /**\n     * Gets the package component of a qualified class name.\n     *\n     * @throws IllegalArgumentException if {@code className} does not match\n     *             {@link #QUALIFIED_CLASS_NAME_RE}\n     */\n    public static String getPackageName(String className) {\n        String simpleName = getSimpleName(className);\n        return className.substring(0, className.length() - simpleName.length() - 1);\n    }\n\n    /**\n     * Gets the annotation of type {@code annotationType} directly present on {@code element}.\n     *\n     * @return {@code null} if an annotation of type {@code annotationType} is not on\n     *         {@code element}","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java#L194-L230","documentation":"AbstractProcessor.getSimpleName(String) parses a fully qualified class name using the regex (?:[a-z]\\\\w*\\\\.)+([A-Z].*) — package components must start with a lowercase letter and the simple name must start with an uppercase letter. If the string does not match (no package part, uppercase-starting package segment, lowercase simple name, array/primitive names), it throws IllegalArgumentException at runtime inside the annotation processor. Callers hit this as a processing-time crash, often with a message naming the offending string.","triggerScenarios":"Calling getSimpleName (or getPackageName, which delegates to it) with a value like 'MyClass' (no package), 'com.Testnode.lower' or 'MyPkg.Foo' — i.e. anything violating '(?:[a-z]\\\\w*\\\\.)+([A-Z].*)'. Inside the processor suite this typically happens when a node/processor metadata lookup receives an unexpected or synthetic class name.","commonSituations":"Annotation processors fed simple names instead of qualified names (e.g. from Class.getSimpleName() or a missed package prefix); packages whose names start with uppercase (violating conventions); refactoring tooling that generates names like 'Outer$Inner' or array descriptors passed where a plain qualified name was expected.","solutions":["Pass a fully qualified name whose package segments start lowercase and whose simple name starts uppercase, e.g. 'com.mycompany.mynode.MyNode'.","If you only have a simple name, prepend the correct package before calling getSimpleName/getPackageName.","If the name is synthetic (inner classes, arrays), normalize it first (replace '$' handling, strip array descriptors) before parsing.","If a package legitimately starts uppercase, rename it to follow Java conventions."],"exampleFix":"// before\nString simple = AbstractProcessor.getSimpleName(\"MyNode\"); // throws\n\n// after\nString simple = AbstractProcessor.getSimpleName(\"org.graalvm.compiler.nodes.MyNode\");","handlingStrategy":"try-catch","validationCode":"private static final Pattern QUALIFIED = Pattern.compile(\"(?:[a-z]\\\\w*\\\\.)+([A-Z].*)\");\n\nstatic boolean isParsableQualifiedName(String className) {\n    return className != null && QUALIFIED.matcher(className).matches();\n}\n\n// use before calling AbstractProcessor.getSimpleName/getPackageName\nif (!isParsableQualifiedName(name)) {\n    name = expectedPackage + \".\" + name; // or skip/reject\n}","typeGuard":null,"tryCatchPattern":"try {\n    String simple = AbstractProcessor.getSimpleName(className);\n} catch (IllegalArgumentException e) {\n    // log the offending name and skip this element; do not retry with the same string\n}","preventionTips":["Always pass fully qualified names (package lowercase-first segments, class uppercase-first) to getSimpleName/getPackageName.","Never feed Class.getSimpleName(), array descriptors, or '$'-containing inner-class names into these helpers without normalizing.","Follow Java naming conventions for packages (lowercase) — the regex hard-codes them."],"tags":["java","graalvm","annotation-processing","naming","runtime-exception"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}