stanfordnlp/CoreNLP · error · SsurgeonParseException

Unmatched quote in string to parse

Error message

Unmatched quote in string to parse

What it means

Ssurgeon.parseArgs tokenizes an argument string with a quote-aware scanner. If a quote character opens a quoted argument but the string ends without a closing quote, SsurgeonParseException('Unmatched quote in string to parse') is thrown.

Solutions

  1. Count the quotes on the failing edit line and add the missing closing quote.
  2. Remove quotes entirely if the value has no spaces and doesn't need quoting.
  3. Use single-token unquoted values where possible to avoid quote handling.
  4. Escape or rewrite values that legitimately contain quote characters so pairs match.

Example fix

// before
editten -node node -lemma "copied text
// after
editten -node node -lemma "copied text"
Defensive patterns

Strategy: validation

Validate before calling

if (line.chars().filter(c -> c == '"').count() % 2 != 0)
  throw new IllegalArgumentException("Unmatched quote in ssurgeon line: " + line);

Try / catch

try { parseSsurgeon(text); } catch (SsurgeonParseException e) { if (e.getMessage().contains("Unmatched quote")) log.error("Fix quotes in: " + text); }

Prevention

When it happens

Trigger: An ssurgeon edit line whose argument value contains a '"' with no matching closing quote, e.g. -lemma "run. A stray quote in a value such as -value he said "hello without the terminator.

Common situations: Copy-pasted rules from documentation where quotes were mangled; escaping confusion (nested quotes in annotation values); editors or shell scripts stripping the final quote from a rule line.

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


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

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/Ssurgeon.java:509

   * This is a specialized args parser, as we want to split on
   * whitespace, but retain everything inside quotes, so we can pass
   * in hashmaps in String form.
   */
  private static List<Pair<String, String>> parseArgs(String argsString) {
    List<String> retList = new ArrayList<>();
    String patternString = "(?:[^\\s\\\"]++|\\\"[^\\\"]*+\\\"|(\\\"))++";
    Pattern pattern = Pattern.compile(patternString);
    Matcher matcher = pattern.matcher(argsString);
    while (matcher.find()) {
      if (matcher.group(1) == null) {
        String matched = matcher.group();
        if (matched.charAt(0) == '"' &&
            matched.charAt(matched.length()-1) == '"')
          retList.add(matched.substring(1, matched.length()-1));
        else
          retList.add(matched);
      }  else
        throw new SsurgeonParseException("Unmatched quote in string to parse");
    }

    List<Pair<String, String>> parsedArgs = new ArrayList<>();
    for (int i = 0; i < retList.size() - 1; i += 2) {
      parsedArgs.add(new Pair<>(retList.get(i), retList.get(i + 1)));
    }
    return parsedArgs;
  }

  private static SsurgeonArgs parseArgsBox(String args, Map<String, String> additionalArgs) {
    SsurgeonArgs argsBox = new SsurgeonArgs();
    List<Pair<String, String>> argsArray = parseArgs(args);
    for (String additional : additionalArgs.keySet()) {
      argsArray.add(new Pair<>("-" + additional, additionalArgs.get(additional)));
    }

    for (Pair<String, String> arg : argsArray) {
      String argsKey = arg.first;

View on GitHub (pinned to 1b7edd19c4)