{"record":{"id":"ce8784dd94c21bc1","repo":"facebook/flow","slug":"unterminated-quote-in-argument-string-arg-string","errorCode":null,"errorMessage":"Unterminated quote in argument string: {arg_string}","messagePattern":"Unterminated quote in argument string: (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_dev_tools/src/runtests/check_exec_file_promise.rs","lineNumber":111,"sourceCode":"            had_quote = true;\n        } else if ch.is_whitespace() {\n            if !current.is_empty() || had_quote {\n                args.push(std::mem::take(&mut current));\n                had_quote = false;\n            }\n        } else if ch == '\\\\' {\n            if let Some(next) = chars.next() {\n                current.push(next);\n            } else {\n                current.push('\\\\');\n            }\n        } else {\n            current.push(ch);\n        }\n    }\n\n    if quote.is_some() {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            format!(\"Unterminated quote in argument string: {arg_string}\"),\n        ));\n    }\n    if !current.is_empty() || had_quote {\n        args.push(current);\n    }\n    Ok(args)\n}\n\npub(super) fn exec_file(\n    cmd: &str,\n    args: &[String],\n    options: &ExecOptions,\n    stdin_data: Option<&str>,\n) -> io::Result<ExecResult> {\n    flow_tokio_runtime::block_on(async {\n        let mut command = Command::new(cmd);","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_dev_tools/src/runtests/check_exec_file_promise.rs#L93-L129","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before (exec file arg string): opening double quote never closed\nrun flow check --focus \" Unclosed\n\n# after: close the quote, or drop it entirely\nrun flow check --focus \"Unclosed\"\nrun flow check --focus Unclosed","handlingStrategy":"validation","validationCode":"// Reject exec-file arg strings with unbalanced quotes before running the check.\nfn quotes_balanced(s: &str) -> bool {\n    let (mut in_sq, mut in_dq, mut esc) = (false, false, false);\n    for c in s.chars() {\n        if esc { esc = false; continue; }\n        match c {\n            '\\\\' => esc = true,\n            '\\'' if !in_dq => in_sq = !in_sq,\n            '\"' if !in_sq => in_dq = !in_dq,\n            _ => {}\n        }\n    }\n    !in_sq && !in_dq\n}","typeGuard":"fn is_unterminated_quote(e: &std::io::Error) -> bool {\n    e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains(\"Unterminated quote\")\n}","tryCatchPattern":"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.","preventionTips":["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."],"tags":["runtests","exec-file","quoting","parse-error","rust"],"backgroundTag":"shell-quoting-error","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}