{"record":{"id":"96e5c71b0fb8b686","repo":"quarkusio/quarkus","slug":"unexpected-character-str-charat-pos-at-posit","errorCode":null,"errorMessage":"Unexpected character '${str.charAt(pos)}' at position ${pos}: ${str}","messagePattern":"Unexpected character '(.+?)' at position (.+?): (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/types/TypeParser.java","lineNumber":221,"sourceCode":"\n        // token is a keyword or fully qualified name\n        int begin = pos;\n        while (pos < str.length() && Character.isJavaIdentifierStart(str.charAt(pos))) {\n            do {\n                pos++;\n            } while (pos < str.length() && Character.isJavaIdentifierPart(str.charAt(pos)));\n\n            if (pos < str.length() && str.charAt(pos) == '.') {\n                pos++;\n            } else {\n                return str.substring(begin, pos);\n            }\n        }\n\n        if (pos == str.length()) {\n            throw new IllegalArgumentException(\"Unexpected end of input: \" + str);\n        }\n        throw new IllegalArgumentException(\"Unexpected character '\" + str.charAt(pos) + \"' at position \" + pos + \": \" + str);\n    }\n\n    private String nextToken() {\n        String result = peekToken();\n        pos += result.length();\n        return result;\n    }\n\n    private boolean isSpecial(char c) {\n        return c == ',' || c == '?' || c == '<' || c == '>' || c == '[' || c == ']';\n    }\n}\n","sourceCodeStart":203,"sourceCodeEnd":234,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/types/TypeParser.java#L203-L234","documentation":"peekToken() throws this IllegalArgumentException when it encounters a character that cannot begin or continue a valid token in a Java type signature at the given position. It is the sibling of the 'Unexpected end of input' error and includes the offending character, its position, and the full string to make the malformed input easy to locate.","triggerScenarios":"Parsing strings containing characters outside the token alphabet — e.g. 'java.util.List<String>' (unqualified generic name with a bare 'S' is fine, but 'java.util.List@' or 'com.Foo;extra' contain characters the lexer does not accept), stray semicolons, commas in wrong places, or ASCII artifacts from copy/paste.","commonSituations":"Users pasting descriptor-style or internal names (e.g. 'Ljava/util/List;' with semicolons) into APIs that expect source-style names; typos in configured class names; strings containing whitespace or control characters not handled by the tokenizer.","solutions":["Read the position reported in the message and inspect that character in the string","Remove or replace the illegal character; use fully qualified binary names for reference types","Do not pass JVM descriptor syntax ('Ljava/lang/String;') where a source-like name ('java.lang.String') is expected","Pre-validate the signature with a regex/checksum or unit test before parsing"],"exampleFix":"// before\nnew TypeParser(\"Ljava/util/List;\").parse(); // Unexpected character ';' at position 14\n// after\nnew TypeParser(\"java.util.List\").parse();","handlingStrategy":"validation","validationCode":"boolean isSourceStyleTypeName(String s) {\n    return s != null && s.matches(\"[\\\\w.$]+(<[\\\\s\\\\S]+>)?(\\\\[\\\\])*\");\n}","typeGuard":"// convert JVM descriptor form to source-style before parsing\nString normalizeToSourceName(String s) {\n    if (s != null && s.startsWith(\"L\") && s.endsWith(\";\")) {\n        return s.substring(1, s.length() - 1).replace('/', '.');\n    }\n    return s;\n}","tryCatchPattern":"try {\n    new TypeParser(sig).parse();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unexpected character\")) {\n        int pos = Integer.parseInt(e.getMessage().replaceFirst(\".*position (\\\\d+):.*\", \"$1\"));\n        throw new IllegalArgumentException(\"Illegal char at index \" + pos + \" in \" + sig, e);\n    }\n    throw e;\n}","preventionTips":["Use source-style names (java.lang.String), not descriptors (Ljava/lang/String;)","Strip whitespace and control characters before parsing","Copy type names from canonical sources (class.getName()), not from bytecode dumps","Sanitize user-supplied type strings with a strict regex"],"tags":["type-parser","parsing","illegal-character"],"backgroundTag":"malformed-type-signature","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}