Skip to content

🐛 useSortedAttributes auto-fix duplicates a JSX attribute and drops another when both an outer JSX element and one of its nested JSX-valued attributes have unsorted attributes #9884

@the-mike

Description

@the-mike

Environment information

Details
CLI:
  Version:                      2.4.10
  Color support:                true

Platform:
  CPU Architecture:             aarch64
  OS:                           macos

Environment:
  BIOME_LOG_PATH:                    unset
  BIOME_LOG_PREFIX_NAME:             unset
  BIOME_LOG_LEVEL:                   unset
  BIOME_LOG_KIND:                    unset
  BIOME_CONFIG_PATH:                 unset
  BIOME_THREADS:                     unset
  BIOME_WATCHER_KIND:                unset
  BIOME_WATCHER_POLLING_INTERVAL:    unset
  NO_COLOR:                     unset
  TERM:                         xterm-256color
  JS_RUNTIME_VERSION:           v24.14.0
  JS_RUNTIME_NAME:              node
  NODE_PACKAGE_MANAGER:         bun/1.3.11

Biome Configuration:
  Status:                       Loaded successfully
  Path:                         biome.jsonc
  Formatter enabled:            true
  Linter enabled:               true
  Assist enabled:               true
  VCS enabled:                  true
  HTML full support enabled:    unset

Workspace:
  Open Documents:

What happened?

When assist/source/useSortedAttributes runs against a JSX element whose attributes are unsorted and at least one attribute value is a nested JSX element whose own attributes are also unsorted, the auto-fix corrupts the source: it produces a JSX element with one attribute duplicated and one silently dropped. The output then trips Biome's own lint/suspicious/noDuplicateJsxProps rule on the very next pass, so biome check --write produces source that fails biome check.

The bug requires both outer and nested attributes to need sorting in the same fix pass. If either side is already sorted, the fix runs cleanly.

Steps to reproduce

Repro.tsx:

declare const Outer: (p: { z: string; a: unknown }) => unknown;
declare const Inner: (p: { z: number; a: number }) => unknown;

export function Repro() {
  return (
    <Outer
      z="x"
      a={
        <Inner
          z={1}
          a={2}
        />
      }
    />
  );
}
bun x biome --version
# Version: 2.4.10
bun x biome check --write --only=assist/source/useSortedAttributes Repro.tsx

(Equivalent: bun x biome check --write Repro.tsx. The --only form proves it is only this single assist action — the formatter and linter are not involved.)

Expected result

Attributes sorted alphabetically on both elements:

declare const Outer: (p: { z: string; a: unknown }) => unknown;
declare const Inner: (p: { z: number; a: number }) => unknown;

export function Repro() {
  return (
    <Outer
      a={
        <Inner
          a={2}
          z={1}
        />
      }
      z="x"
    />
  );
}

Actual output

declare const Outer: (p: { z: string; a: unknown }) => unknown;
declare const Inner: (p: { z: number; a: number }) => unknown;

export function Repro() {
  return <Outer a={<Inner a={2} z={1} />} a={<Inner a={2} z={1} />} />;
}

Note on the <Outer> element:

  • a={<Inner a={2} z={1} />} appears twice back-to-back.
  • z="x" is missing entirely.

A subsequent bun x biome check Repro.tsx then reports:

src/Repro.tsx:5:17 lint/suspicious/noDuplicateJsxProps
  × This JSX property is assigned multiple times.

So the assist action has produced source that fails Biome's own linter.

Subcommand isolation

The bug is exclusive to the assist subsystem. Tested against the same pristine input:

Command Outcome
biome format --write Repro.tsx clean (no change)
biome lint --write Repro.tsx clean (no change)
biome check --write Repro.tsx bug fires
biome check --write --only=assist/source/useSortedAttributes Repro.tsx bug fires

|
Per the Biome assist docs, biome format and biome lint do not run assist actions — only check (and ci) do. So the failure is in the assist action itself, not in the formatter or any lint rule.

Code of Conduct

  • I agree to follow Biome's Code of Conduct

Standalone reproduction package

A self-contained Vite + React + TypeScript project that demonstrates this bug end-to-end (including a ./reproduce.sh script that asserts the bug fires) is available at: https://github.com/the-mike/biome-usesortedattributes-bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    S-Needs triageStatus: this issue needs to be triaged

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions