rust-lang/rust-analyzer · error · anyhow::Error

Failed to parse `build.target` as an array of target

Error message

Failed to parse `build.target` as an array of target

What it means

When reading `[build] target` from a Cargo config file, rust-analyzer's `parse_toml_cargo_config_build_target` accepts either a single string or an array of strings. If the TOML value is neither (e.g. an integer, boolean, or table), it returns the anyhow error `Failed to parse \`build.target\` as an array of target` via the shared `parse_err` message.

Source

Thrown at crates/project-model/src/toolchain_info/target_tuple.rs:103

            s.to_owned()
        }
    };

    let parse_err = "Failed to parse `build.target` as an array of target";

    match target.as_ref() {
        toml::de::DeValue::String(s) => {
            Ok(Some(vec![join_to_origin_if_json_path(s.as_ref(), target)]))
        }
        toml::de::DeValue::Array(arr) => arr
            .iter()
            .map(|v| {
                let s = v.as_ref().as_str().context(parse_err)?;
                Ok(join_to_origin_if_json_path(s, v))
            })
            .collect::<anyhow::Result<_>>()
            .map(Option::Some),
        _ => Err(anyhow::anyhow!(parse_err)),
    }
}

#[cfg(test)]
mod tests {
    use paths::{AbsPathBuf, Utf8PathBuf};

    use crate::{ManifestPath, Sysroot};

    use super::*;

    #[test]
    fn cargo() {
        let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
        let sysroot = Sysroot::empty();
        let manifest_path =
            ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
        let cfg = QueryConfig::Cargo(&sysroot, &manifest_path, &None);

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Set `build.target` to a string: `build.target = "x86_64-unknown-linux-gnu"`.
  2. Or use an array of strings for multiple targets: `build.target = ["a", "b"]`.
  3. Remove any non-string/non-array value from the key and re-run `cargo check` to confirm the config is valid.
  4. Verify with `cargo config get build.target` (cargo-config) or by building, since cargo itself would also reject it.

Example fix

# before (.cargo/config.toml)
[build]
target = 3

# after (.cargo/config.toml)
[build]
target = "x86_64-unknown-linux-gnu"
Defensive patterns

Strategy: validation

Validate before calling

// validate build.target shape before handing config to the consumer
fn validate_build_target(cfg: &toml::Value) -> Result<(), String> {
    match cfg.get("build").and_then(|b| b.get("target")) {
        None | Some(toml::Value::String(_)) => Ok(()),
        Some(toml::Value::Array(a)) if a.iter().all(|v| v.is_str()) => Ok(()),
        Some(other) => Err(format!("build.target must be string or string array, got: {other}")),
    }
}

Type guard

fn is_string_or_string_array(v: &toml::Value) -> bool {
    v.is_str() || matches!(v, toml::Value::Array(a) if a.iter().all(toml::Value::is_str))
}

Try / catch

match load_cargo_config(path) {
    Err(e) if e.to_string().contains("Failed to parse `build.target`") => {
        eprintln!("fix [build] target in .cargo/config.toml: must be a string or array of strings");
        fallback_to_default_target()
    }
    other => other,
}

Prevention

When it happens

Trigger: A `.cargo/config.toml` or `.cargo/config` whose `build.target` is set to a non-string non-array value (e.g. `build.target = 3` or a nested table). Triggered when rust-analyzer loads the cargo config through `cargo_config_build_target`.

Common situations: Hand-editing config.toml and forgetting quotes around the target triple, tools writing structured values into the key, or copying JSON-style config where the value became an object.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/d882786703674e65. Report an issue: GitHub.