rust-lang/cargo · error

Deprecated dependency sections are unsupported: {}

Error message

Deprecated dependency sections are unsupported: {}

What it means

Thrown by `cargo add` when the target manifest still uses the deprecated dependency table names `dev_dependencies` / `build_dependencies` (or `target.<t>.dev_dependencies` / `target.<t>.build_dependencies`). cargo-add cannot reliably mutate these legacy sections, so it refuses to proceed and asks the user to migrate them to the hyphenated forms (`dev-dependencies`, `build-dependencies`). The check runs unconditionally in `add()` right after the manifest is loaded via `LocalManifest::try_new`, before any dependency resolution.

Source

Thrown at src/ops/cargo_add/mod.rs:86

    /// Whether the minimum supported Rust version should be considered during resolution
    pub honor_rust_version: Option<bool>,
}

/// Add dependencies to a manifest
pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<()> {
    let dep_table = options
        .section
        .to_table()
        .into_iter()
        .map(String::from)
        .collect::<Vec<_>>();

    let manifest_path = options.spec.manifest_path().to_path_buf();
    let mut manifest = LocalManifest::try_new(&manifest_path)?;
    let original_raw_manifest = manifest.to_string();
    let legacy = manifest.get_legacy_sections();
    if !legacy.is_empty() {
        anyhow::bail!(
            "Deprecated dependency sections are unsupported: {}",
            legacy.join(", ")
        );
    }

    let mut registry = workspace.package_registry()?;

    let deps = {
        let _lock = options
            .gctx
            .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
        registry.lock_patches();
        options
            .dependencies
            .iter()
            .map(|raw| {
                resolve_dependency(
                    &manifest,

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Open the named manifest and rename every `[dev_dependencies]` to `[dev-dependencies]` and `[build_dependencies]` to `[build-dependencies]`, including any under `[target.'cfg(...)']`.
  2. Re-run `cargo add` once the section names are hyphenated; `get_legacy_sections()` will now return an empty Vec and the bail is skipped.
  3. Run `cargo fix --edition` or a TOML linter that normalizes dependency table names to prevent recurrence.

Example fix

// before (Cargo.toml)
[dev_dependencies]
serde_json = "1"

// after
[dev-dependencies]
serde_json = "1"
Defensive patterns

Strategy: validation

Validate before calling

// Before calling ops::add, ensure the manifest has no legacy sections.
use cargo_util_schemas::manifest;

fn has_legacy_sections(text: &str) -> Result<(), Vec<String>> {
    let doc: toml_edit::ImDocument<_> = toml_edit::ImDocument::parse(text).unwrap();
    let mut bad = Vec::new();
    for k in ["dev_dependencies", "build_dependencies"] {
        if doc.as_table().contains_key(k) { bad.push(k.to_string()); }
    }
    if bad.is_empty() { Ok(()) } else { Err(bad) }
}

// let manifest_text = std::fs::read_to_string(&manifest_path)?;
// has_legacy_sections(&manifest_text).map_err(|bad| anyhow::anyhow!("rename to hyphenated: {bad:?}"))?;

Prevention

When it happens

Trigger: A `Cargo.toml` containing `[dev_dependencies]` or `[build_dependencies]` (underscores) and then invoking `cargo add <dep>` (or `cargo add <dep> --dev`). `get_legacy_sections()` returns any matching top-level or `target.*` keys, and if the resulting list is non-empty the function bails with the section names joined by ", ".

Common situations: Older crates created before the hyphen convention was enforced, manifests authored by hand, or manifests generated by tooling that emitted underscores. The error is environmental (the file being edited), not a bug in the caller's dependency choice.

Related errors


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