{"record":{"id":"0a19cc44014e55c2","repo":"antlr/antlr4","slug":"could-not-create-checksum","errorCode":null,"errorMessage":"Could not create checksum {}","messagePattern":"Could not create checksum (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/MojoUtils.java","lineNumber":47,"sourceCode":"            MessageDigest complete = MessageDigest.getInstance(\"MD5\");\n\n            try {\n                int n;\n\n                do {\n                    n = in.read(buffer);\n\n                    if (n > 0) {\n                        complete.update(buffer, 0, n);\n                    }\n                } while (n != -1);\n            } finally {\n                in.close();\n            }\n\n            return complete.digest();\n        } catch (NoSuchAlgorithmException ex) {\n            throw new IOException(\"Could not create checksum \" + file, ex);\n        }\n    }\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","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/MojoUtils.java#L29-L65","documentation":"The inverse delimiter imbalance in split(pattern): more stop delimiters than start delimiters means a stop appeared with no matching start, so 'missing start tag' IllegalArgumentException is thrown. The scanner cannot decide which text belongs to a tag versus literal text when the pairing is broken.","triggerScenarios":"Patterns like \"ID> = <ID>\" (stray '>' in text), or text containing the stop delimiter character without it being part of a tag.","commonSituations":"Matching expression grammars whose literal text includes '>' (comparisons, generics-like syntax, arrows '->'); forgetting to escape a literal stop delimiter.","solutions":["Escape literal '>' characters in text chunks with the escape sequence (e.g. \\\\>).","Use custom delimiters that do not occur in the target syntax.","Lint patterns for balanced delimiters before compiling."],"exampleFix":"// before\nParseTreePattern p = m.compile(\"a > <ID>\", R.expr); // stray '>' counts as stop\n\n// after\nParseTreePattern p = m.compile(\"a \\\\> <ID>\", R.expr);","handlingStrategy":"try-catch","validationCode":"long starts = pattern.chars().filter(c -> c == '<').count();\nlong stops  = pattern.chars().filter(c -> c == '>').count();\nif (starts < stops) throw new IllegalArgumentException(\"missing start tag: \" + pattern);","typeGuard":"boolean hasBalancedTags(String p) {\n    return p.chars().filter(c -> c=='<').count() == p.chars().filter(c -> c=='>').count();\n}","tryCatchPattern":"try {\n    pattern = matcher.compile(patternText, ruleIndex);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"missing start tag\")) {\n        patternText = escapeLiteralStops(patternText);\n        pattern = matcher.compile(patternText, ruleIndex);\n    } else throw e;\n}","preventionTips":["Escape literal '>' characters in text chunks.","Choose delimiters absent from the target syntax for comparison-heavy grammars.","Validate delimiter balance before compile."],"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"}