linebender/druid · error

Duplicate attribute

Error message

Duplicate attribute

What it means

While parsing #[lens(...)] field attributes, the lens(ignore) option may appear at most once per item. Specifying lens(ignore) (or repeating the ignore path) twice triggers this compile-time error at the second occurrence's span.

Solutions

  1. Remove the duplicate lens(ignore) — one occurrence is enough to exclude the field from the lens.
  2. Review the field's attribute list and deduplicate options.
  3. If you meant to ignore two different fields, put one #[lens(ignore)] on each field.

Example fix

// before
#[lens(ignore, ignore)]
screen: ScreenId,
// after
#[lens(ignore)]
screen: ScreenId,
Defensive patterns

Strategy: validation

Validate before calling

// Deduplicate lens options before compiling:
fn check_no_dup_ignore(attrs: &[&str]) -> Result<(), String> {
    let count = attrs.iter().filter(|a| **a == "ignore").count();
    if count > 1 { Err("lens(ignore) specified more than once".into()) } else { Ok(()) }
}

Prevention

When it happens

Trigger: Writing #[lens(ignore, ignore)] on the same field, or repeating the ignore path in two different nested forms within one attribute list.

Common situations: Merging fields or copy-pasting attribute lines when refactoring struct definitions, resulting in a duplicated ignore directive.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/d16d8918aef27deb. Report an issue: GitHub.

Appendix: source

Thrown at druid-derive/src/attr.rs:222

        let mut ignore = false;
        let mut lens_name_override = None;

        for attr in field.attrs.iter() {
            if attr.path.is_ident(BASE_DRUID_DEPRECATED_ATTR_PATH) {
                panic!(
                    "The 'druid' attribute has been replaced with separate \
                    'lens' and 'data' attributes.",
                );
            } else if attr.path.is_ident(BASE_LENS_ATTR_PATH) {
                match attr.parse_meta()? {
                    Meta::List(meta) => {
                        for nested in meta.nested.iter() {
                            match nested {
                                NestedMeta::Meta(Meta::Path(path))
                                    if path.is_ident(IGNORE_ATTR_PATH) =>
                                {
                                    if ignore {
                                        return Err(Error::new(
                                            nested.span(),
                                            "Duplicate attribute",
                                        ));
                                    }
                                    ignore = true;
                                }
                                NestedMeta::Meta(Meta::NameValue(meta))
                                    if meta.path.is_ident(LENS_NAME_OVERRIDE_ATTR_PATH) =>
                                {
                                    if lens_name_override.is_some() {
                                        return Err(Error::new(meta.span(), "Duplicate attribute"));
                                    }

                                    let ident = parse_lit_into_ident(&meta.lit)?;
                                    lens_name_override = Some(ident);
                                }
                                other => return Err(Error::new(other.span(), "Unknown attribute")),
                            }

View on GitHub (pinned to 0f8b1195e4)