{"record":{"id":"df467c4eca861c39","repo":"astral-sh/ruff","slug":"can-only-write-to-stdout-when-formatting-from-stdi","errorCode":null,"errorMessage":"Can only write to stdout when formatting from stdin, but you asked for {:?}","messagePattern":"Can only write to stdout when formatting from stdin, but you asked for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_python_formatter/src/main.rs","lineNumber":22,"sourceCode":"\nuse anyhow::{Context, Result, bail};\nuse clap::Parser as ClapParser;\n\nuse ruff_python_formatter::cli::{Cli, Emit, format_and_debug_print};\n\n/// Read a `String` from `stdin`.\nfn read_from_stdin() -> Result<String> {\n    let mut buffer = String::new();\n    io::stdin().lock().read_to_string(&mut buffer)?;\n    Ok(buffer)\n}\n\nfn main() -> Result<()> {\n    let cli: Cli = Cli::parse();\n\n    if cli.files.is_empty() {\n        if !matches!(cli.emit, None | Some(Emit::Stdout)) {\n            bail!(\n                \"Can only write to stdout when formatting from stdin, but you asked for {:?}\",\n                cli.emit\n            );\n        }\n        let source = read_from_stdin()?;\n        // It seems reasonable to give this a dummy name\n        let formatted = format_and_debug_print(&source, &cli, Path::new(\"stdin.py\"))?;\n        if cli.check {\n            if formatted == source {\n                return Ok(());\n            }\n            bail!(\"Content not correctly formatted\")\n        }\n        stdout().lock().write_all(formatted.as_bytes())?;\n    } else {\n        for file in &cli.files {\n            let source = fs::read_to_string(file)\n                .with_context(|| format!(\"Could not read {}: \", file.display()))?;","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_python_formatter/src/main.rs#L4-L40","documentation":"This is the standalone debug binary of the Python formatter. When no files are given, it formats stdin and writes the result to stdout; a non-stdout `--emit` mode is then meaningless, so `main` bails with this anyhow error naming the requested emit mode.","triggerScenarios":"Running `ruff_python_formatter` (dev binary) with no file arguments while passing `--emit json` (or any `Emit` variant other than stdout).","commonSituations":"Copying emit flags from the main `ruff format` CLI into the formatter debug binary; scripting the debug binary expecting JSON output from stdin.","solutions":["Drop the `--emit` flag when piping source via stdin","Pass actual file paths as arguments if you want non-stdout behavior from the normal ruff CLI instead","Use the main `ruff` binary, which supports `--emit` for file-based runs"],"exampleFix":"// before\nruff_python_formatter --emit json < file.py\n// after\nruff_python_formatter < file.py","handlingStrategy":"validation","validationCode":"# shell check before invoking\nif [ -t 0 ] && [ $# -eq 0 ]; then echo \"stdin expected: drop --emit\"; fi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only pass --emit when actual file paths are supplied","Remember the debug binary reads stdin when no files are given","Use the main ruff binary for emit modes other than stdout"],"tags":["ruff","formatter","cli","stdin"],"backgroundTag":"incompatible-cli-flags","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}