{"record":{"id":"8bb9c02c2078ce4d","repo":"bazelbuild/bazel","slug":"unfinished-quote-s-at-s","errorCode":null,"errorMessage":"Unfinished quote %s at %s","messagePattern":"Unfinished quote (.+?) at (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/ShellQuotedParamsFilePreProcessor.java","lineNumber":134,"sourceCode":"            quoted = true;\n            quoteStart = position;\n          } else if (current == '\\r') {\n            char next = read();\n            if (next == '\\n') {\n              return arg.toString();\n            } else {\n              unread(next);\n              return arg.toString();\n            }\n          } else if (Character.isWhitespace(current)) {\n            return arg.toString();\n          } else {\n            arg.append(current);\n          }\n        }\n      }\n      if (quoted) {\n        throw new IOException(\n            String.format(UNFINISHED_QUOTE_MESSAGE_FORMAT, \"'\", quoteStart));\n      }\n      return arg.toString();\n    }\n  }\n}\n","sourceCodeStart":116,"sourceCodeEnd":141,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/ShellQuotedParamsFilePreProcessor.java#L116-L141","documentation":"ShellQuotedParamsFilePreProcessor tokenizes a shell-quoted params file character by character, tracking quotes starting at a position (quoteStart). If end-of-input is reached while still inside a quote, it throws IOException 'Unfinished quote' with the quote character and the 1-based position where the quote opened. Parsing aborts before the tokens ever reach option parsing.","triggerScenarios":"A params file (default shell quoting) containing an unmatched single or double quote, e.g. a value like -Xss'-... or \"C:\\dir without a closing quote; also multi-line strings whose closing quote was lost.","commonSituations":"Hand-editing args files and dropping a closing quote; Windows paths with embedded quotes; escaping rules differing between the generating shell and Bazel's POSIX tokenizer; trailing quote removed by sed/cleanup scripts.","solutions":["Open the params file at the reported position and add the matching closing quote","Prefer --param_file=file_format=multiline (one arg per line, no shell quoting) when values contain quotes or backslashes","Validate args files in CI: a quick check that single/double quote counts balance per POSIX rules"],"exampleFix":"# before (args.txt)\n--per_file_copt=\"//third_party/.* @-Werror\n# after\n--per_file_copt=\"//third_party/.*@-Werror\"\n# or use multiline format: bazel build --param_file=file_format=multiline @args.txt","handlingStrategy":"validation","validationCode":"# POSIX-ish balance check for single and double quotes per line (outside comments)\nwhile IFS= read -r line; do\n  case \"$line\" in \\#*) continue;; esac\n  s=$(printf '%s' \"$line\" | tr -cd \"'\" | wc -c); d=$(printf '%s' \"$line\" | tr -cd '\"' | wc -c)\n  [ $((s % 2)) -eq 0 ] && [ $((d % 2)) -eq 0 ] || { echo \"Unbalanced quotes: $line\" >&2; exit 2; }\ndone < args.txt","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer multiline format (--param_file=file_format=multiline) for values with quotes","Generate shell-quoted files with a proper shlex-style escaper, not string concat","Avoid editing quoted args files by hand; regenerate them"],"tags":["bazel","options","params-file","shell-quoting","parsing"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}