{"record":{"id":"35e36d155c39bb7d","repo":"antlr/antlr4","slug":"expected-to-be-prefixed-with","errorCode":null,"errorMessage":"expected {} to be prefixed with {}","messagePattern":"expected (.+?) to be prefixed with (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/MojoUtils.java","lineNumber":67,"sourceCode":"    }\n\n    /**\n     * Given the source directory File object and the full PATH to a grammar, produce the\n     * path to the named grammar file in relative terms to the {@code sourceDirectory}.\n     * This will then allow ANTLR to produce output relative to the base of the output\n     * directory and reflect the input organization of the grammar files.\n     *\n     * @param   sourceDirectory  The source directory {@link File} object\n     * @param   grammarFileName  The full path to the input grammar file\n     *\n     * @return  The path to the grammar file relative to the source directory\n     */\n    public static String findSourceSubdir(File sourceDirectory, File grammarFile) {\n        String srcPath = sourceDirectory.getPath() + File.separator;\n        String path = grammarFile.getPath();\n\n        if (!path.startsWith(srcPath)) {\n            throw new IllegalArgumentException(\"expected \" + path +\n                \" to be prefixed with \" + sourceDirectory);\n        }\n\n        File unprefixedGrammarFileName = new File(path.substring(srcPath.length()));\n\n        if (unprefixedGrammarFileName.getParent() == null) {\n            return \"\";\n        }\n\n        return unprefixedGrammarFileName.getParent() + File.separator;\n    }\n}\n","sourceCodeStart":49,"sourceCodeEnd":80,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/MojoUtils.java#L49-L80","documentation":"After counts balance, split(pattern) pairs each start with its stop in order and requires starts.get(i) < stops.get(i). A start delimiter appearing at or after its paired stop (e.g. '> <' with swapped custom delimiters) means the delimiters enclose nothing or are inverted, so 'tag delimiters out of order' IllegalArgumentException is thrown.","triggerScenarios":"Custom delimiters where start and stop are swapped or identical (setDelimiters(\"%\", \"%\")); patterns where an empty tag '<>' degenerates so the computed start offset is >= stop offset after ordering.","commonSituations":"Choosing symmetric custom delimiters; converting existing patterns when delimiters change and the ordering assumptions silently break.","solutions":["Use distinct start and stop delimiters with start occurring before stop in each tag.","Avoid identical start/stop delimiter strings.","Re-inspect patterns after changing delimiters via setDelimiters."],"exampleFix":"// before\nmatcher.setDelimiters(\"%\", \"%\", \"\\\\\"); // same delimiter -> ordering breaks\nm.compile(\"%id%\", R.expr);\n\n// after\nmatcher.setDelimiters(\"<<\", \">>\", \"\\\\\");\nm.compile(\"<<id>>\", R.expr);","handlingStrategy":"try-catch","validationCode":"// with custom delimiters, verify pairing order before compiling\nList<Integer> s = indexOfAll(pattern, startDelim), t = indexOfAll(pattern, stopDelim);\nboolean ordered = s.size() == t.size() && IntStream.range(0, s.size()).allMatch(i -> s.get(i) < t.get(i));\nif (!ordered) throw new IllegalArgumentException(\"tag delimiters out of order: \" + pattern);","typeGuard":null,"tryCatchPattern":"try {\n    pattern = matcher.compile(patternText, ruleIndex);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"tag delimiters out of order\")) {\n        reportDelimiterMisconfiguration();\n    }\n    throw e;\n}","preventionTips":["Use distinct start and stop delimiters that appear in order within each tag.","Never configure identical start and stop delimiters.","Re-validate all patterns whenever setDelimiters changes."],"tags":["antlr","java","parse-tree-pattern","pattern-syntax","delimiters"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}