rust-lang/cargo · error

`lints. . ` is not a valid lint name

Error message

`lints.{tool}.{name}` is not a valid lint name

What it means

Thrown during [lints] validation when a lint name contains '::' but the prefix does not match the tool name and is not a supported tool under 'rust'. This is the catch-all for unrecognized namespaced lint keys — e.g. [lints.rust] 'foo::bar' where 'foo' is unknown. Unlike the other two branches, no fix suggestion is offered because the intended location is unknown.

Solutions

  1. Remove the '::' and use the lint's bare name under the correct tool table (most rustc/clippy lints are bare names under [lints.rust]).
  2. Verify the lint exists in the target tool's lint list.
  3. If the lint is from a plugin, check whether [lints] supports it at all.

Example fix

# before
[lints.rust]
"clippy::needless_return" = "warn"  # '::' form is invalid here

# after
[lints.rust]
clippy_needless_return = "warn"  # or configure clippy via [lints] with the correct bare name per docs
Defensive patterns

Strategy: validation

Validate before calling

fn lint_name_recognized(tool: &str, name: &str, supported: &[&str]) -> Result<(), String> {
    if name.contains("::") {
        let prefix = name.split_once("::").unwrap().0;
        let known = prefix == tool || (tool == "rust" && supported.contains(&prefix));
        if !known {
            return Err(format!("unrecognized lint name `{name}` under [lints.{tool}]; remove `::` or verify the lint exists"));
        }
    }
    Ok(())
}

Type guard

fn is_valid_lint_key(tool: &str, name: &str, supported: &[&str]) -> bool {
    if let Some((prefix, _)) = name.split_once("::") {
        return prefix == tool || (tool == "rust" && supported.contains(&prefix));
    }
    true
}

Prevention

When it happens

Trigger: Writing a [lints] entry with a '::' in the name where the prefix is neither the current tool nor a recognized tool. For example [lints.rust] "unknown::lint" = "warn".

Common situations: A developer guesses a lint name that does not exist or misremembers the namespace. A typo in the prefix. Using a clippy lint under [lints.rust] without realizing clippy lints are bare names under [lints.rust] (clippy lints don't use '::').

Related errors


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

Appendix: source

Thrown at src/workspace/parser/mod.rs:2745

            }
            if let Some(existing) = seen_normalized.get(&normalized) {
                warnings.push(format!(
                    "duplicate lint `{existing}` in `[lints.{tool}]`, \
                     conflicts with `{name}` and will not work in a future edition"
                ));
            }
            seen_normalized.insert(normalized.clone(), name.to_string());
            if let Some((prefix, suffix)) = name.split_once("::") {
                if tool == prefix {
                    anyhow::bail!(
                        "`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`"
                    )
                } else if tool == "rust" && supported.contains(&prefix) {
                    anyhow::bail!(
                        "`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`"
                    )
                } else {
                    anyhow::bail!("`lints.{tool}.{name}` is not a valid lint name")
                }
            } else if let Some(config) = config.config() {
                for config_name in config.keys() {
                    // manually report unused manifest key warning since we collect all the "extra"
                    // keys and values inside the config table
                    let expected = EXPECTED_LINT_CONFIG.contains(&(tool, name, config_name));
                    if !expected {
                        let message =
                            format!("unused manifest key: `lints.{tool}.{name}.{config_name}`");
                        warnings.push(message);
                    }
                }
            }
        }
    }

    Ok(())
}

View on GitHub (pinned to 98a09e7e7d)