{"record":{"id":"071b0c7f6d04c39c","repo":"oracle/graal","slug":"binary-property-s-cannot-appear-to-the-left-of","errorCode":null,"errorMessage":"Binary property %s cannot appear to the left of '=' in a Unicode property escape","messagePattern":"Binary property (.+?) cannot appear to the left of '=' in a Unicode property escape","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeProperties.java","lineNumber":176,"sourceCode":"    private String normalizePropertySpec(String propertySpec) {\n        int equals = propertySpec.indexOf('=');\n        if (equals >= 0) {\n            String propertyName = normalizePropertyName(propertySpec.substring(0, equals));\n            String propertyValue = propertySpec.substring(equals + 1);\n            switch (propertyName) {\n                case \"blk\":\n                    propertyValue = normalizeBlockName(propertyValue);\n                    break;\n                case \"gc\":\n                    propertyValue = normalizeGeneralCategoryName(propertyValue);\n                    break;\n                case \"sc\":\n                case \"scx\":\n                    propertyValue = normalizeScriptName(propertyValue);\n                    break;\n                default:\n                    CompilerDirectives.transferToInterpreterAndInvalidate();\n                    throw new IllegalArgumentException(String.format(\"Binary property %s cannot appear to the left of '=' in a Unicode property escape\", propertySpec.substring(0, equals)));\n            }\n            return propertyName + \"=\" + propertyValue;\n        } else if (isSupportedGeneralCategory(propertySpec)) {\n            return \"gc=\" + normalizeGeneralCategoryName(propertySpec);\n        } else {\n            return normalizePropertyName(propertySpec);\n        }\n    }\n\n    private String normalizePropertyName(String propertyName) {\n        String name = returnOrThrow(propertyName, \"character property\", data.lookupPropertyAlias(propertyName, nameMatchingMode));\n        if (!withOtherProperties() && OTHER_PROPERTIES_NAMES_SET.contains(name)) {\n            throw new IllegalArgumentException(String.format(\"Unsupported Unicode character property '%s'\", propertyName));\n        }\n        return name;\n    }\n\n    private String normalizeGeneralCategoryName(String generalCategoryName) {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeProperties.java#L158-L194","documentation":"UnicodeProperties.normalizePropertySpec accepts the form 'name=value' only for enumerated properties where name is blk (block), gc (general category), sc/scx (script / script extensions). A binary (boolean) property name on the left of '=', such as \\p{Alphabetic=Yes}, has no defined value space, so it throws IllegalArgumentException.","triggerScenarios":"Writing \\p{BinaryName=...} in a pattern, e.g. \\p{Alpha=true}, \\p{Uppercase=Yes}, or any \\p{X=Y} where X is not blk/gc/sc/scx after alias lookup.","commonSituations":"Patterns ported from PCRE/ICU/.NET, which accept forms like \\p{Alpha=Y} or \\p{Alphabetic: Yes}; users assuming java.util.regex-style boolean syntax generalizes to '=' forms.","solutions":["Use binary properties without '=value': \\p{Alphabetic} instead of \\p{Alphabetic=Yes}.","For enumerated values keep only the supported left-hand names: blk=, gc=, sc=, scx= (e.g. \\p{sc=Greek}, \\p{gc=Lu}).","If you generate patterns programmatically, normalize property syntax to these forms before compilation."],"exampleFix":"// before\nString p = \"\\\\p{Alphabetic=Yes}+\"; // binary property with '=' -> throws\n\n// after\nString p = \"\\\\p{Alphabetic}+\"; // or enumerated form: \"\\\\p{gc=L}+\"","handlingStrategy":"validation","validationCode":"import java.util.Set;\nprivate static final Set<String> ENUMERATED_LEFT_HAND = Set.of(\"blk\", \"gc\", \"sc\", \"scx\");\n\nstatic String normalizeEscape(String spec) {\n    int eq = spec.indexOf('=');\n    if (eq < 0) return spec; // binary property form is fine\n    String lhs = spec.substring(0, eq);\n    if (!ENUMERATED_LEFT_HAND.contains(lhs)) {\n        return lhs; // drop '=value' -> use the binary form \\p{lhs}\n    }\n    return spec;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use binary properties without '=value' and keep '=' forms to blk/gc/sc/scx only.","Normalize patterns from PCRE/ICU sources before compiling on TRegex.","Add pattern linting in CI for \\p{...=...} syntax when patterns cross engines."],"tags":["regex","truffle","unicode","property-escape","syntax"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}