Skip to content

Web: duplicate resource URIs collide on the React list key in ResourceControls #2206

Description

@cliffhall

Summary

The Resources panel keys its list on resource.uri, so a server whose
resources/list result contains the same URI twice makes React log
Encountered two children with the same key on every render — and, per React's
own warning, may duplicate or omit one of the rows.

This is the same defect class as #1957 (duplicate tools/list names leaving
stale rows after filtering), which was fixed for tools. The resources list
appears not to have been covered by that change.

What was observed

While a third-party MCP Apps server was connected to web:dev, the browser
console logged this several hundred times — repeating on every re-render, in
bursts as the UI updated:

Encountered two children with the same key, `ui://hello-world/app.html`.
Keys should be unique so that components maintain their identity across
updates. Non-unique keys may cause children to be duplicated and/or omitted —
the behavior is unsupported and could change in a future version.

Where it comes from

clients/web/src/components/groups/ResourceControls/ResourceControls.tsx:317

{filteredResources.map((resource) => (
  <ResourceListItem
    key={resource.uri}
    ...

Two neighbouring lists in the same file take the same shape and look equally
exposed: key={template.uriTemplate} (line 343) and key={sub.resource.uri}
(line 386). RootsTable.tsx:66 (key={root.uri}) is a fourth.

The store is not the source of the duplication: ManagedListState.applyItems
(core/mcp/state/managedListState.ts:351) replaces this.items wholesale rather
than appending, so repeated refreshes cannot accumulate copies. That points at
the fetched list itself carrying the URI twice — either because the server
advertises it twice, or because the paginating fetchAll overlaps pages.
Which of those two it is has not been established.

Status of this report — not reproduced

Filed from console output captured in a live session, not from a reproduction.
Specifically unconfirmed:

  • hello-world is not one of this repo's test-servers/, so the server
    involved was external and is not identified here. No fixture in-repo currently
    reproduces it.
  • Whether the duplicate URI originates server-side or in fetchAll pagination.
  • Whether a row was actually dropped or duplicated on screen, or the warning was
    the only visible symptom.

First step for whoever picks this up is a synthetic fixture serving a
resources/list with a repeated URI — the same approach #1957 used for tools.

Expected

A duplicate URI in resources/list should render without a React key collision,
and every returned entry should be visible, matching the behavior #1957
established for duplicate tool names.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingv2Issues and PRs for v2

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions