bazelbuild/bazel · error · IOException

Unfinished quote %s at %s

Error message

Unfinished quote %s at %s

What it means

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.

Source

Thrown at src/main/java/com/google/devtools/common/options/ShellQuotedParamsFilePreProcessor.java:134

            quoted = true;
            quoteStart = position;
          } else if (current == '\r') {
            char next = read();
            if (next == '\n') {
              return arg.toString();
            } else {
              unread(next);
              return arg.toString();
            }
          } else if (Character.isWhitespace(current)) {
            return arg.toString();
          } else {
            arg.append(current);
          }
        }
      }
      if (quoted) {
        throw new IOException(
            String.format(UNFINISHED_QUOTE_MESSAGE_FORMAT, "'", quoteStart));
      }
      return arg.toString();
    }
  }
}

View on GitHub (pinned to e6e199d060)

Solutions

  1. Open the params file at the reported position and add the matching closing quote
  2. Prefer --param_file=file_format=multiline (one arg per line, no shell quoting) when values contain quotes or backslashes
  3. Validate args files in CI: a quick check that single/double quote counts balance per POSIX rules

Example fix

# before (args.txt)
--per_file_copt="//third_party/.* @-Werror
# after
--per_file_copt="//third_party/.*@-Werror"
# or use multiline format: bazel build --param_file=file_format=multiline @args.txt
Defensive patterns

Strategy: validation

Validate before calling

# POSIX-ish balance check for single and double quotes per line (outside comments)
while IFS= read -r line; do
  case "$line" in \#*) continue;; esac
  s=$(printf '%s' "$line" | tr -cd "'" | wc -c); d=$(printf '%s' "$line" | tr -cd '"' | wc -c)
  [ $((s % 2)) -eq 0 ] && [ $((d % 2)) -eq 0 ] || { echo "Unbalanced quotes: $line" >&2; exit 2; }
done < args.txt

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/8bb9c02c2078ce4d. Report an issue: GitHub.