influxdata/influxdb · error · syn::Error

duplicate `id`

Error message

duplicate `id`

What it means

A compile-time proc-macro error raised by the catalog record attribute parser when the same attribute argument `id` appears more than once on a record definition; only one `id = ...` is allowed, so the macro aborts expansion.

Solutions

  1. Remove one of the duplicate `id = ...` entries
  2. Keep exactly one `id = record_ids::SOME_CONST` per attribute

Example fix

// before
#[catalog(id = record_ids::A, id = record_ids::B, shape = 0x1)]
// after
#[catalog(id = record_ids::A, shape = 0x1)]
Defensive patterns

Strategy: validation

Validate before calling

fn check_no_dupes(args: &[&str]) -> Result<(), String> {
    let mut seen = std::collections::HashSet::new();
    for a in args {
        if !seen.insert(a) { return Err(format!("duplicate argument `{a}`")); }
    }
    Ok(())
}

Prevention

When it happens

Trigger: Writing `#[catalog(id = A, id = B, shape = ...)]` — two `id` arguments in one attribute.

Common situations: Merging two attribute examples and leaving both `id` lines; generating attributes programmatically and appending a default id; copy-paste duplication.

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 influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/1667305482a7db55. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_catalog_macros/src/lib.rs:94

        let mut flags = None;

        for meta in metas {
            let Meta::NameValue(nv) = meta else {
                return Err(syn::Error::new(
                    meta.span(),
                    "expected `name = value`; supported arguments are `id`, `shape`, `flags`",
                ));
            };
            let key = nv
                .path
                .get_ident()
                .ok_or_else(|| syn::Error::new(nv.path.span(), "expected an argument name"))?
                .to_string();

            match key.as_str() {
                "id" => {
                    if id.replace(nv.value).is_some() {
                        return Err(syn::Error::new(nv.path.span(), "duplicate `id`"));
                    }
                }
                "shape" => {
                    let span = nv.value.span();
                    let Expr::Lit(syn::ExprLit {
                        lit: syn::Lit::Int(lit),
                        ..
                    }) = nv.value
                    else {
                        return Err(syn::Error::new(
                            span,
                            "`shape` must be an integer literal, e.g. `shape = 0xbba17476`",
                        ));
                    };
                    if shape.replace(lit).is_some() {
                        return Err(syn::Error::new(nv.path.span(), "duplicate `shape`"));
                    }
                }

View on GitHub (pinned to 06200ef96b)