oxc-project/oxc · error · OxcDiagnostic

Duplicate key '{key_value}' found in JSX elements

Error message

Duplicate key '{key_value}' found in JSX elements

What it means

react/jsx-key diagnostic emitted when the warnOnDuplicates option is true (the default in oxlint, again stricter than eslint-plugin-react) and two sibling elements — children of one JSX element/fragment, or elements within one array literal — carry the same key value. Duplicate keys break React's assumption that keys uniquely identify siblings, which can cause state to attach to the wrong component when lists reorder. The help text reminds that each child in a list should have a unique key.

Source

Thrown at crates/oxc_linter/src/rules/react/jsx_key.rs:50

}

fn missing_key_prop_for_element_in_iterator(iter_span: Span, el_span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(r#"Missing "key" prop for element in iterator."#)
        .with_help(r#"Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)."#)
        .with_labels([
            iter_span.label("Iterator starts here."),
            el_span.label("Element generated here."),
        ])
}

fn key_prop_must_be_placed_before_spread(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(r#""key" prop must be placed before any `{...spread}`"#)
        .with_help("To avoid conflicting with React's new JSX transform: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html")
        .with_label(span)
}

fn duplicate_key_prop(key_value: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Duplicate key '{key_value}' found in JSX elements"))
        .with_help("Each child in a list should have a unique 'key' prop")
        .with_label(span)
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[schemars(transparent)]
pub struct JsxKey(Box<JsxKeyConfig>);

#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct JsxKeyConfig {
    /// When true, require key prop to be placed before any spread props
    #[serde(default = "default_true")]
    pub check_key_must_before_spread: bool,
    /// When true, warn on duplicate key values
    #[serde(default = "default_true")]
    pub warn_on_duplicates: bool,
    /// When true, check fragment shorthand `<>` for keys

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Give every sibling a unique key, ideally derived from a stable id: <Row key={item.id}/>
  2. If the data has duplicate ids, compose a unique key: key={`${item.id}-${index}`} or key={`${section}-${item.id}`}
  3. Fix map callbacks that return constant or copy-pasted keys
  4. If migrating from ESLint and you want the old behavior, set warnOnDuplicates: false in the jsx-key options of .oxlintrc.json

Example fix

// before
{items.map(i => <Row key="row" data={i}/>)}

// after
{items.map(i => <Row key={i.id} data={i}/>)}
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -D react/jsx-key src/  # warnOnDuplicates defaults to true in oxlint

Prevention

When it happens

Trigger: Two children with key="same" on one parent: <><Row key="a"/><Row key="a"/></>; a map whose callback returns a constant key (items.map(i => <Row key="x"/>)); hardcoded keys copy-pasted across branches (key="item" in both a ternary's arms); duplicate keys among JSX elements in one array expression.

Common situations: Copy-pasted list branches; keys derived from a non-unique field (name instead of id); index-based keys colliding with literal keys after a refactor; data genuinely containing duplicate ids that must be disambiguated with a prefix/suffix.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/85313cd29465b76c. Report an issue: GitHub.