rust-lang/cargo · error

failed to merge config value from

Error message

failed to merge config value from `{}` into `{}`: expected {}, but found {}

What it means

While merging layered Cargo config values, a non-list/non-table value's type changed in an incompatible way (e.g. a string in one layer, a table in another, or a list where a scalar was expected). The merge explicitly forbids type switches except between scalars, so it bails with the key path, expected vs found descriptors, and their definitions.

Solutions

  1. Read `expected.definition()` and `found.definition()` from the message to locate both files/lines.
  2. Make the value types consistent across all config layers (both scalars, both tables, or both lists).
  3. Remove the conflicting override from the lower-priority layer.
  4. Use `cargo config get <key>` to inspect the merged value and its sources.

Example fix

// before
# ~/.cargo/config.toml
[build]
jobs = 4
# ./.cargo/config.toml (typo created a table)
[build.jobs]
default = true

// after
[build]
jobs = "default"
Defensive patterns

Strategy: validation

Validate before calling

fn types_compatible(a: &ConfigValue, b: &ConfigValue) -> bool {
    matches!((a, b), (CV::List(_,_), CV::List(_,_)) | (CV::Table(_,_), CV::Table(_,_))) || (!matches!(a, CV::List(_,_) | CV::Table(_,_)) && !matches!(b, CV::List(_,_) | CV::Table(_,_)))
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Two config layers (e.g. `~/.cargo/config.toml` and project `.cargo/config.toml`, or CLI `--config` overrides) define the same key with different TOML types; e.g. `build.jobs = 4` in one and `[build.jobs]` (table) in another.

Common situations: Merging global and project configs after a refactor; `--config` flag passing a JSON-encoded value whose type differs from the file value; typos that turn a scalar into a section header.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/6353477f8f911ea3. Report an issue: GitHub.

Appendix: source

Thrown at src/context/config_value.rs:205

                                     {} and {}",
                                    key,
                                    entry.definition(),
                                    new_def,
                                )
                            })?;
                        }
                        Entry::Vacant(entry) => {
                            entry.insert(value);
                        }
                    };
                }
            }
            // Allow switching types except for tables or arrays.
            (expected @ &mut CV::List(_, _), found)
            | (expected @ &mut CV::Table(_, _), found)
            | (expected, found @ CV::List(_, _))
            | (expected, found @ CV::Table(_, _)) => {
                return Err(anyhow!(
                    "failed to merge config value from `{}` into `{}`: expected {}, but found {}",
                    found.definition(),
                    expected.definition(),
                    expected.desc(),
                    found.desc()
                ));
            }
            (old, mut new) => {
                if force || is_higher_priority {
                    mem::swap(old, &mut new);
                }
            }
        }

        Ok(())
    }

    pub fn i64(&self, key: &str) -> CargoResult<(i64, &Definition)> {

View on GitHub (pinned to eb98b54bc9)