rust-lang/cargo · error

expected table for configuration key

Error message

expected table for configuration key `{}`, but found {} in {}

What it means

Cargo raises this hard error when resolving a configuration key whose intermediate value must be a table (e.g. `target.x.y` or `[foo]` sections) but the stored value is a scalar (integer, string, list, or boolean) instead. It is thrown in get_cv_helper while walking the config key path: a prefix of the requested key resolved to a non-table CV variant, so a nested key cannot exist beneath it. The message names the truncated key, the found value's description, and the file:line where that value was defined.

Solutions

  1. Open the config file named in the error (the `in <file>` part) and change the scalar value into a TOML table, e.g. replace `target = "..."` with a `[target."<triple>"]` section.
  2. Check for duplicate definitions across all config sources (system, global ~/.cargo/config.toml, project .cargo/config.toml) and remove the one that defines the key as a scalar.
  3. Verify quoting for keys that contain hyphens or dots, e.g. [target.'cfg(all(unix, target_arch = "x86_64"))'].

Example fix

// before: .cargo/config.toml
target = "x86_64-unknown-linux-gnu"

// after: .cargo/config.toml
[target.x86_64-unknown-linux-gnu]
linker = "clang"
Defensive patterns

Strategy: validation

Validate before calling

// TOML / shell check before invoking cargo
grep -n '^\s*target\s*=' ~/.cargo/config.toml .cargo/config.toml 2>/dev/null || true
# any hit means `target` (or the failing key prefix) is a scalar, not a table — fix it

Type guard

fn is_table(v: &toml::Value) -> bool { matches!(v, toml::Value::Table(_)) }

Try / catch

match gctx.get::<String>(&["target", triple, "linker"]) {
    Err(e) if e.to_string().contains("expected table for configuration key") => {
        // fall back to default / repair config
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling config lookups such as gctx.get(...) with a multi-part key (e.g. ["target", "x86_64-unknown-linux-gnu", "linker"]) where a prefix like `target` or `target.<triple>` was defined in a config file as a scalar — for example `target = "x86_64-linux"` instead of `target."x86_64-..." = ...`, or a `[foo]` table accidentally overridden by a `foo = ...` scalar in a later config source.

Common situations: Typos or wrong nesting in ~/.cargo/config.toml or .cargo/config.toml (defining `target` as a string instead of a table); merging config sources where one file uses TOML key syntax `foo = value` and another uses `[foo]` tables, silently replacing the table with a scalar; environment-variable-based config where dotted names don't produce nested tables.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-09-22). Data as JSON: /api/errors/f7ab5251e87c92a7. Report an issue: GitHub.

Appendix: source

Thrown at src/context/mod.rs:871

        }
        let mut parts = key.parts().enumerate();
        let Some(mut val) = vals.get(parts.next().unwrap().1) else {
            return Ok(None);
        };
        for (i, part) in parts {
            match val {
                CV::Table(map, _) => {
                    val = match map.get(part) {
                        Some(val) => val,
                        None => return Ok(None),
                    }
                }
                CV::Integer(_, def)
                | CV::String(_, def)
                | CV::List(_, def)
                | CV::Boolean(_, def) => {
                    let key_so_far = ConfigKey::from_parts(key.parts().take(i));
                    bail!(
                        "expected table for configuration key `{}`, \
                         but found {} in {}",
                        key_so_far,
                        val.desc(),
                        def
                    )
                }
            }
        }
        Ok(Some(val.clone()))
    }

    /// This is a helper for getting a CV from a file or env var.
    pub(crate) fn get_cv_with_env(&self, key: &ConfigKey) -> CargoResult<Option<CV>> {
        // Determine if value comes from env, cli, or file, and merge env if
        // possible.
        let cv = self.get_cv(key)?;
        if key.is_root() {

View on GitHub (pinned to 98a09e7e7d)