facebook/flow · error

failed to flush stdout

Error message

failed to flush stdout

What it means

`flow save-state` sends a SAVE_STATE request to the server; on success it prints the server's confirmation message and flushes stdout. The saved state was already written server-side before this point, so a panic here does not mean the save failed — only that printing the confirmation to a dead or full stdout failed (BrokenPipe / ENOSPC), and the expect turns that into a crash with a nonzero exit code.

Source

Thrown at rust_port/crates/flow_cli/src/save_state_command.rs:89

            )
        }
        (Some(true), None) => server_prot::request::SaveStateOut::Scm,
        (_, Some(out)) => server_prot::request::SaveStateOut::File(std::path::PathBuf::from(
            flow_common::files::imaginary_realpath(&out),
        )),
    };

    let request = server_prot::request::Command::SAVE_STATE { out };
    let response =
        command_utils::connect_and_make_request(&flowconfig_name, &connect_flags, &root, &request);
    match response {
        server_prot::response::Response::SAVE_STATE(Err(msg)) => {
            eprintln!("{}", msg);
            flow_common_exit_status::exit(flow_common_exit_status::FlowExitStatus::UnknownError)
        }
        server_prot::response::Response::SAVE_STATE(Ok(msg)) => {
            println!("{}", msg);
            std::io::stdout().flush().expect("failed to flush stdout");
        }
        response => command_utils::failwith_bad_response(&request, &response),
    }
}

pub(crate) fn command() -> command_spec::Command {
    command_spec::command(spec(), main)
}

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Run `flow save-state` without piping into short-lived consumers, or redirect to a file with free space.
  2. Check disk space on the redirect target.
  3. Verify the save actually succeeded via the server (server logs / subsequent load) — the panic is only about printing the message.
  4. Maintainer fix: treat BrokenPipe on the final flush as success and exit 0.

Example fix

// before
println!("{}", msg);
std::io::stdout().flush().expect("failed to flush stdout");

// after
println!("{}", msg);
if let Err(e) = std::io::stdout().flush() {
    if e.kind() != std::io::ErrorKind::BrokenPipe {
        panic!("failed to flush stdout: {}", e);
    }
    // reader went away; the save-state already succeeded
    std::process::exit(0);
}
Defensive patterns

Strategy: try-catch

Try / catch

println!("{}", msg);
if let Err(e) = std::io::stdout().flush() {
    if e.kind() != std::io::ErrorKind::BrokenPipe {
        panic!("failed to flush stdout: {}", e);
    }
    std::process::exit(0); // save-state already succeeded server-side
}

Prevention

When it happens

Trigger: `flow save-state | head -c 10` (consumer exits after a few bytes); stdout redirected to a full filesystem; stdout fd closed (`>&-`); a scripting wrapper that stops reading flow's output once it sees the first bytes.

Common situations: Automation piping save-state output through short-reading consumers; CI disks at capacity; wrapper scripts that discard output early.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/06bfb04967b025c2. Report an issue: GitHub.