stanfordnlp/CoreNLP · error · RuntimeException

ERROR: Unknown macro ""!

Error message

ERROR: Unknown macro ""!

What it means

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.

Solutions

  1. Define the macro before use with a line like 'macro NAME = pattern'
  2. Fix the macro name spelling/case at the usage site
  3. Verify the batch file loaded all macro-definition lines (they must appear before dependent lines)

Example fix

// before
$ANIMAL = dog   (used as: $ANIMALS pattern)
// after
$ANIMALS = dog  (definition matches usage)
Defensive patterns

Strategy: validation

Validate before calling

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));

Try / catch

try { parser.parse(lines, macros); } catch (RuntimeException e) { log.error(e.getMessage()); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/b7eef6d49d4881f1. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/SemgrexBatchParser.java:75

      SemgrexPattern pattern = SemgrexPattern.compile(line, env);
      patterns.add(pattern);
    }
    return patterns;
  }

  private static final Pattern MACRO_NAME_PATTERN = Pattern.compile("\\$\\{[a-z0-9]+\\}", Pattern.CASE_INSENSITIVE);

  private static String replaceMacros(String line, Map<String, String> macros) {
    StringBuilder out = new StringBuilder();
    Matcher matcher = MACRO_NAME_PATTERN.matcher(line);
    int offset = 0;
    while(matcher.find(offset)) {
      int start = matcher.start();
      int end = matcher.end();
      String name = line.substring(start + 2, end - 1);
      String value = macros.get(name);
      if(value == null){
        throw new RuntimeException("ERROR: Unknown macro \"" + name + "\"!");
      }
      if(start > offset) {
        out.append(line.substring(offset, start));
      }
      out.append(value);
      offset = end;
    }
    if(offset < line.length()) out.append(line.substring(offset));
    String postProcessed =  out.toString();
    if(!postProcessed.equals(line) && VERBOSE) log.info("Line \"" + line + "\" changed to \"" + postProcessed + '"');
    return postProcessed;
  }

  private static Map<String, String> preprocess(BufferedReader reader) throws IOException {
    Map<String, String> macros = Generics.newHashMap();
    for(String line; (line = reader.readLine()) != null; ) {
      line = line.trim();
      if(line.startsWith("macro ")){

View on GitHub (pinned to 1b7edd19c4)