{"record":{"id":"b624ad2e834c0b20","repo":"stanfordnlp/CoreNLP","slug":"unmatched-quote-in-string-to-parse","errorCode":null,"errorMessage":"Unmatched quote in string to parse","messagePattern":"Unmatched quote in string to parse","errorType":"exception","errorClass":"SsurgeonParseException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/Ssurgeon.java","lineNumber":509,"sourceCode":"   * This is a specialized args parser, as we want to split on\n   * whitespace, but retain everything inside quotes, so we can pass\n   * in hashmaps in String form.\n   */\n  private static List<Pair<String, String>> parseArgs(String argsString) {\n    List<String> retList = new ArrayList<>();\n    String patternString = \"(?:[^\\\\s\\\\\\\"]++|\\\\\\\"[^\\\\\\\"]*+\\\\\\\"|(\\\\\\\"))++\";\n    Pattern pattern = Pattern.compile(patternString);\n    Matcher matcher = pattern.matcher(argsString);\n    while (matcher.find()) {\n      if (matcher.group(1) == null) {\n        String matched = matcher.group();\n        if (matched.charAt(0) == '\"' &&\n            matched.charAt(matched.length()-1) == '\"')\n          retList.add(matched.substring(1, matched.length()-1));\n        else\n          retList.add(matched);\n      }  else\n        throw new SsurgeonParseException(\"Unmatched quote in string to parse\");\n    }\n\n    List<Pair<String, String>> parsedArgs = new ArrayList<>();\n    for (int i = 0; i < retList.size() - 1; i += 2) {\n      parsedArgs.add(new Pair<>(retList.get(i), retList.get(i + 1)));\n    }\n    return parsedArgs;\n  }\n\n  private static SsurgeonArgs parseArgsBox(String args, Map<String, String> additionalArgs) {\n    SsurgeonArgs argsBox = new SsurgeonArgs();\n    List<Pair<String, String>> argsArray = parseArgs(args);\n    for (String additional : additionalArgs.keySet()) {\n      argsArray.add(new Pair<>(\"-\" + additional, additionalArgs.get(additional)));\n    }\n\n    for (Pair<String, String> arg : argsArray) {\n      String argsKey = arg.first;","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/Ssurgeon.java#L491-L527","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Count the quotes on the failing edit line and add the missing closing quote.","Remove quotes entirely if the value has no spaces and doesn't need quoting.","Use single-token unquoted values where possible to avoid quote handling.","Escape or rewrite values that legitimately contain quote characters so pairs match."],"exampleFix":"// before\neditten -node node -lemma \"copied text\n// after\neditten -node node -lemma \"copied text\"","handlingStrategy":"validation","validationCode":"if (line.chars().filter(c -> c == '\"').count() % 2 != 0)\n  throw new IllegalArgumentException(\"Unmatched quote in ssurgeon line: \" + line);","typeGuard":null,"tryCatchPattern":"try { parseSsurgeon(text); } catch (SsurgeonParseException e) { if (e.getMessage().contains(\"Unmatched quote\")) log.error(\"Fix quotes in: \" + text); }","preventionTips":["Keep quote characters in pairs on each edit line","Avoid quoting single-token values","Lint ssurgeon rule files with a quote-count check in CI"],"tags":["parsing","ssurgeon","string-tokenization"],"backgroundTag":"invalid-argument-format","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}