facebook/flow · error · std::io::Error
Unterminated quote in argument string: {arg_string}
Error message
Unterminated quote in argument string: {arg_string} What it means
check_exec_file_promise parses an exec-file test fixture's argument string with shell-like rules: single/double quotes group words and a backslash escapes the next character. The parser tracks the open quote across the whole string; if a quote is opened and never closed before end-of-input, it aborts with ErrorKind::InvalidInput "Unterminated quote in argument string: {arg_string}" (the full offending string is included).
Source
Thrown at rust_port/crates/flow_dev_tools/src/runtests/check_exec_file_promise.rs:111
had_quote = true;
} else if ch.is_whitespace() {
if !current.is_empty() || had_quote {
args.push(std::mem::take(&mut current));
had_quote = false;
}
} else if ch == '\\' {
if let Some(next) = chars.next() {
current.push(next);
} else {
current.push('\\');
}
} else {
current.push(ch);
}
}
if quote.is_some() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Unterminated quote in argument string: {arg_string}"),
));
}
if !current.is_empty() || had_quote {
args.push(current);
}
Ok(args)
}
pub(super) fn exec_file(
cmd: &str,
args: &[String],
options: &ExecOptions,
stdin_data: Option<&str>,
) -> io::Result<ExecResult> {
flow_tokio_runtime::block_on(async {
let mut command = Command::new(cmd);View on GitHub (pinned to f88ac94bcf)
Solutions
- Balance the quotes in the fixture's argument string — every opening quote needs a closing one.
- Escape literal quotes with a backslash (\") or wrap the word in the other quote type ("it's" instead of it's).
- After any JSON/tooling round-trip of the fixture, re-check that escapes survived (a consumed closing quote is the usual damage).
Example fix
# before (exec file arg string): opening double quote never closed run flow check --focus " Unclosed # after: close the quote, or drop it entirely run flow check --focus "Unclosed" run flow check --focus Unclosed
Defensive patterns
Strategy: validation
Validate before calling
// Reject exec-file arg strings with unbalanced quotes before running the check.
fn quotes_balanced(s: &str) -> bool {
let (mut in_sq, mut in_dq, mut esc) = (false, false, false);
for c in s.chars() {
if esc { esc = false; continue; }
match c {
'\\' => esc = true,
'\'' if !in_dq => in_sq = !in_sq,
'"' if !in_sq => in_dq = !in_dq,
_ => {}
}
}
!in_sq && !in_dq
} Type guard
fn is_unterminated_quote(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("Unterminated quote")
} Try / catch
On InvalidInput 'Unterminated quote', report the exec-file name and its args field (the message already embeds the full string) — guide the fix to the fixture, not to the command being run.
Prevention
- Quote only whole words; escape literal quotes with a backslash.
- Lint fixtures in CI with a quote-parity check before running them.
- Re-check escapes after any JSON round-trip of the fixture.
When it happens
Trigger: An exec-file fixture whose args string contains an unmatched quote character, e.g. `--focus "Unclosed` or `it's`, where the quote opens a group that never closes before the end of the string.
Common situations: Hand-written exec fixtures; apostrophes inside unquoted words (don't, it's) treated as quote starts; a closing quote lost through JSON double-escaping when the fixture was machine-generated; copy-pasting shell lines into the fixture without rebalancing quotes.
Related errors
- {autofix_error}; additionally failed to stop Flow: {stop_err
- lock file is already held
- invalid line
- invalid column
- failed to write cli errors
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/ce8784dd94c21bc1.
Report an issue: GitHub.