{"record":{"id":"b7eef6d49d4881f1","repo":"stanfordnlp/CoreNLP","slug":"error-unknown-macro","errorCode":null,"errorMessage":"ERROR: Unknown macro \"\"!","messagePattern":"ERROR: Unknown macro \"\"!","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/semgraph/semgrex/SemgrexBatchParser.java","lineNumber":75,"sourceCode":"      SemgrexPattern pattern = SemgrexPattern.compile(line, env);\n      patterns.add(pattern);\n    }\n    return patterns;\n  }\n\n  private static final Pattern MACRO_NAME_PATTERN = Pattern.compile(\"\\\\$\\\\{[a-z0-9]+\\\\}\", Pattern.CASE_INSENSITIVE);\n\n  private static String replaceMacros(String line, Map<String, String> macros) {\n    StringBuilder out = new StringBuilder();\n    Matcher matcher = MACRO_NAME_PATTERN.matcher(line);\n    int offset = 0;\n    while(matcher.find(offset)) {\n      int start = matcher.start();\n      int end = matcher.end();\n      String name = line.substring(start + 2, end - 1);\n      String value = macros.get(name);\n      if(value == null){\n        throw new RuntimeException(\"ERROR: Unknown macro \\\"\" + name + \"\\\"!\");\n      }\n      if(start > offset) {\n        out.append(line.substring(offset, start));\n      }\n      out.append(value);\n      offset = end;\n    }\n    if(offset < line.length()) out.append(line.substring(offset));\n    String postProcessed =  out.toString();\n    if(!postProcessed.equals(line) && VERBOSE) log.info(\"Line \\\"\" + line + \"\\\" changed to \\\"\" + postProcessed + '\"');\n    return postProcessed;\n  }\n\n  private static Map<String, String> preprocess(BufferedReader reader) throws IOException {\n    Map<String, String> macros = Generics.newHashMap();\n    for(String line; (line = reader.readLine()) != null; ) {\n      line = line.trim();\n      if(line.startsWith(\"macro \")){","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/semgraph/semgrex/SemgrexBatchParser.java#L57-L93","documentation":"SemgrexBatchParser.replaceMacros expands $MACRO references in batch-file lines; if a referenced macro name is not present in the macros map, it throws a RuntimeException. This guarantees fail-fast behavior on unresolved macro references.","triggerScenarios":"A line contains $NAME (matching the macro-reference regex) but macros.get(\"NAME\") returns null because the macro was never defined via a 'macro NAME = value' line, was defined after use, or the name is misspelled.","commonSituations":"Using a macro before its definition line in the batch file, case mismatch between definition and usage, or copying a pattern file between projects where macro definitions were dropped.","solutions":["Define the macro before use with a line like 'macro NAME = pattern'","Fix the macro name spelling/case at the usage site","Verify the batch file loaded all macro-definition lines (they must appear before dependent lines)"],"exampleFix":"// before\n$ANIMAL = dog   (used as: $ANIMALS pattern)\n// after\n$ANIMALS = dog  (definition matches usage)","handlingStrategy":"validation","validationCode":"java.util.regex.Matcher m = java.util.regex.Pattern.compile(\"\\\\$([A-Za-z_][A-Za-z0-9_]*)\").matcher(line); while (m.find()) if (!macros.containsKey(m.group(1))) throw new IllegalArgumentException(\"Unknown macro: \" + m.group(1));","typeGuard":null,"tryCatchPattern":"try { parser.parse(lines, macros); } catch (RuntimeException e) { log.error(e.getMessage()); }","preventionTips":["Define all macros before first use in the batch file","Keep macro names case-consistent","Lint batch files for $REF tokens against the defined macro set"],"tags":["java","semgrex","macro","batch-parser"],"backgroundTag":"missing-config-value","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}