rust-lang/cargo · error · io::Error

argument for argfile contains newlines: `{arg}`

Error message

argument for argfile contains newlines: `{arg}`

What it means

Returned as an `io::Error` from the same argfile builder (crates/cargo-util/src/process_builder.rs:480) when an argument passes the UTF-8 check but contains a newline (`\n`). The argfile puts one argument per line, so an embedded newline would silently split one argument into two and corrupt the spawned command, so cargo rejects it up front.

Source

Thrown at crates/cargo-util/src/process_builder.rs:481

        arg.push(tmp.path());
        let mut cmd = self.build_command_without_args();
        cmd.arg(arg);
        tracing::debug!("created argfile at {} for {self}", tmp.path().display());

        let cap = self.get_args().map(|arg| arg.len() + 1).sum::<usize>();
        let mut buf = Vec::with_capacity(cap);
        for arg in &self.args {
            let arg = arg.to_str().ok_or_else(|| {
                io::Error::new(
                    io::ErrorKind::Other,
                    format!(
                        "argument for argfile contains invalid UTF-8 characters: `{}`",
                        arg.to_string_lossy()
                    ),
                )
            })?;
            if arg.contains('\n') {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("argument for argfile contains newlines: `{arg}`"),
                ));
            }
            writeln!(buf, "{arg}")?;
        }
        tmp.write_all(&mut buf)?;
        Ok((cmd, tmp))
    }

    /// Builds a command from `ProcessBuilder` for everything but not `args`.
    fn build_command_without_args(&self) -> Command {
        let mut command = {
            let mut iter = self.wrappers.iter().rev().chain(once(&self.program));
            let mut cmd = Command::new(iter.next().expect("at least one `program` exists"));
            cmd.args(iter);
            cmd
        };

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Strip newline characters from the offending argument (most often an env var like `RUSTFLAGS` or a config value).
  2. Re-enter the value in `.cargo/config.toml` on a single line, avoiding pasted multiline content.
  3. Sanitize any programmatically generated flags before they reach cargo.

Example fix

# before — pasted multiline value
[build]
rustflags = ["--cfg foo
bar"]
# after — single line
[build]
rustflags = ["--cfg foo"]
Defensive patterns

Strategy: validation

Validate before calling

fn args_have_no_newlines(args: &[String]) -> bool { args.iter().all(|a| !a.contains('\n')) }
// assert args_have_no_newlines(&flags) before invoking cargo with large arg sets

Prevention

When it happens

Trigger: An argument to an external process (rustc, linker, etc.) contains a literal `\n`. The check `if arg.contains('\n')` at line 480 fires when building the argfile fallback for long command lines.

Common situations: A feature flag, env var, or RUSTFLAGS value containing a stray newline (copy-paste from a multiline config); a path with a newline (rare); a script-generated `.cargo/config.toml` embedding CR/LF; build tools injecting `\n` into flags.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/05a14b8be4489cc3.json. Report an issue: GitHub.