rust-lang/cargo · warning

ignoring `resolver.feature-unification` without…

Error message

ignoring `resolver.feature-unification` without `-Zfeature-unification`

What it means

In `Workspace::set_resolve_behavior`, the `resolver.feature-unification` config key is only honored under the unstable `-Zfeature-unification` flag. When the key is set in config but the flag is absent, Cargo emits this warning and ignores the setting (falling back to default unification behavior).

Solutions

  1. Run with nightly and pass `-Zfeature-unification` (e.g. `cargo +nightly -Zfeature-unification build`) so the setting takes effect.
  2. Alternatively remove `resolver.feature-unification` from .cargo/config.toml to silence the warning if default behavior is acceptable.
  3. Set `CARGO_UNSTABLE_FEATURE_UNIFICATION=true` in environments where passing -Z on the CLI is impractical.
  4. Verify cargo version supports the feature (check `cargo -Z help`).

Example fix

// before (.cargo/config.toml, stable build)
[resolver]
feature-unification = "selected"
// after: run with
// cargo +nightly -Zfeature-unification build
// or remove the [resolver] section
Defensive patterns

Strategy: validation

Validate before calling

// in CI, before invoking cargo
if grep -q 'feature-unification' .cargo/config.toml; then
  case "$CARGO_CHANNEL" in *nightly*) ;; *) echo "requires -Zfeature-unification on nightly"; exit 1;; esac
fi

Prevention

When it happens

Trigger: Configuring `resolver.feature-unification = "selected"` (or similar) in .cargo/config.toml while building with stable Rust or without `-Zfeature-unification` on nightly.

Common situations: Teams adopting the new feature-unification setting from nightly docs, then running stable CI builds; copy-pasted config from projects using nightly features; forgetting to add `-Z feature-unification` or `cargo +nightly -Z ...`.

Related errors


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

Appendix: source

Thrown at src/workspace/workspace.rs:353

            ResolveBehavior::V3 => {
                if self.resolve_behavior == ResolveBehavior::V3 {
                    self.resolve_honors_rust_version = true;
                }
            }
        }
        let config = self.gctx().get::<CargoResolverConfig>(["resolver"])?;
        if let Some(incompatible_rust_versions) = config.incompatible_rust_versions {
            self.resolve_honors_rust_version =
                incompatible_rust_versions == IncompatibleRustVersions::Fallback;
        }
        if self.gctx().cli_unstable().feature_unification {
            self.resolve_feature_unification = config
                .feature_unification
                .unwrap_or(FeatureUnification::Selected);
        } else if config.feature_unification.is_some() {
            self.gctx()
                .shell()
                .warn("ignoring `resolver.feature-unification` without `-Zfeature-unification`")?;
        };

        if let Some(lockfile_path) = config.lockfile_path {
            // Reserve the ability to add templates in the future.
            let replacements: [(&str, &str); 0] = [];
            let path = lockfile_path
                    .resolve_templated_path(self.gctx(), replacements)
                    .map_err(|e| match e {
                        context::ResolveTemplateError::UnexpectedVariable {
                            variable,
                            raw_template,
                        } => {
                            anyhow!(
                                "unexpected variable `{variable}` in resolver.lockfile-path `{raw_template}`"
                            )
                        }
                        context::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {
                            let (btype, literal) = match bracket_type {

View on GitHub (pinned to 98a09e7e7d)