stanfordnlp/CoreNLP · error · RuntimeException
Found a non-empty line in a tsurgeon section after reading…
Error message
Found a non-empty line in a tsurgeon section after reading the operation
What it means
GenerateTrees.readGrammar reads a grammar file divided into sections (TSURGEON, TERMINALS, etc.). In the TSURGEON section, exactly one operation is expected per entry; any additional non-empty line after the operation has been read means the file is malformed, so it throws with the offending line context.
Solutions
- Edit the grammar file so each tsurgeon operation is separated properly (blank line / next section marker) and no extra non-empty lines follow an operation.
- Split multiple tsurgeon operations into separate operation entries in the section.
- Check for hidden characters or missing newlines around the tsurgeon block reported by the stack trace.
Example fix
// before TSURGEON delete NP-1 move NP > NP // after TSURGEON delete NP-1 TSURGEON move NP > NP
Defensive patterns
Strategy: validation
Validate before calling
// parse the grammar file first and assert each TSURGEON block has exactly one operation before calling readGrammar assertEachTsurgeonBlockHasOneOp(grammarFile);
Try / catch
try { g.readGrammar(reader); } catch (RuntimeException e) { if (e.getMessage().contains("non-empty line in a tsurgeon section")) { throw new GrammarFormatException("fix TSURGEON section: " + e.getMessage(), e); } } Prevention
- Separate tsurgeon operations with blank lines / section markers
- Lint grammar files for stray lines inside TSURGEON sections
- Keep one operation per TSURGEON entry
When it happens
Trigger: A tsurgeon section in the grammar file contains more than one operation's worth of non-empty lines — e.g. two operations without a proper section/blank-line separator, or stray text after the tsurgeon command.
Common situations: Hand-edited grammar files where blank-line separators between tsurgeon operations were removed; concatenating tsurgeon scripts without the expected section formatting; copy-paste artifacts leaving extra lines in the TSURGEON block.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid number of fields, should be >=1 and <= 31
- Error on line
- Unknown minimizer
- Unknown clique: " + clique
- Bad number put into wordToNumber. Word is: \"" + input +…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/32e39d72a93cccd4.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/GenerateTrees.java:134
try {
Section newSection = Section.valueOf(line.toUpperCase(Locale.ROOT));
section = newSection;
if (section == Section.TSURGEON) {
// this will tregex pattern until it has eaten a blank
// line, then read tsurgeon until it has eaten another
// blank line.
Pair<TregexPattern, TsurgeonPattern> operation = Tsurgeon.getOperationFromReader(bin, compiler);
tsurgeons.add(operation);
}
continue;
} catch (IllegalArgumentException e) {
// never mind, not an enum
}
String[] pieces = line.split(" +");
switch(section) {
case TSURGEON: {
throw new RuntimeException("Found a non-empty line in a tsurgeon section after reading the operation");
}
case TERMINALS: {
Counter<String> productions = terminals.get(pieces[0]);
if (productions == null) {
productions = new ClassicCounter<>();
terminals.put(pieces[0], productions);
}
for (int i = 1; i < pieces.length; ++i) {
productions.incrementCount(pieces[i]);
}
break;
}
case NONTERMINALS: {
Counter<List<String>> productions = nonTerminals.get(pieces[0]);
if (productions == null) {
productions = new ClassicCounter<>();
nonTerminals.put(pieces[0], productions);
}View on GitHub (pinned to 1b7edd19c4)