marmelab/react-admin · error · Error

useShowController: Fetched record's id attribute (${record.i

Error message

useShowController: Fetched record's id attribute (${record.id}) must match the requested 'id' (${id})

What it means

After fetching, useShowController verifies that the record returned by the dataProvider actually has the id that was requested. A mismatch means the data layer returned a different record, which would silently show wrong data, so react-admin throws instead.

Source

Thrown at packages/ra-core/src/controller/show/useShowController.ts:120

        { id, meta },
        {
            enabled:
                (!isPendingAuthenticated && !isPendingCanAccess) ||
                disableAuthentication,
            onError: () => {
                notify('ra.notification.item_doesnt_exist', {
                    type: 'error',
                });
                redirect(redirectOnError, resource, id);
            },
            retry: false,
            ...otherQueryOptions,
        }
    );

    // eslint-disable-next-line eqeqeq
    if (record && record.id && record.id != id) {
        throw new Error(
            `useShowController: Fetched record's id attribute (${record.id}) must match the requested 'id' (${id})`
        );
    }

    const getResourceLabel = useGetResourceLabel();
    const recordRepresentation = getRecordRepresentation(record);
    const defaultTitle = translate(`resources.${resource}.page.show`, {
        id,
        record,
        recordRepresentation:
            typeof recordRepresentation === 'string'
                ? recordRepresentation
                : '',
        _: translate('ra.page.show', {
            name: getResourceLabel(resource, 1),
            id,
            record,
            recordRepresentation:

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Fix the dataProvider getOne so the returned data.id equals the requested id
  2. Ensure the id key is named `id` in the returned record (or map your API key, e.g. _id → id)
  3. Return undefined/throw in the dataProvider when the record is not found instead of returning an arbitrary record

Example fix

// before
getOne: async (resource, params) => ({ data: { title: 'foo' } }) // id lost
// after
getOne: async (resource, params) => {
  const raw = await api.fetchOne(resource, params.id);
  return { data: { ...raw, id: raw._id } };
}
Defensive patterns

Strategy: validation

Validate before calling

const { data } = await dataProvider.getOne('posts', { id });
if (data && data.id != id) throw new Error('dataProvider returned wrong record');

Type guard

const matchesId = <T extends { id: Identifier }>(r: T, id: Identifier) => r.id != null && r.id == id;

Try / catch

try { await dataProvider.getOne(r, { id }); } catch (e) { console.error('getOne returned mismatched id', e); }

Prevention

When it happens

Trigger: A custom dataProvider getOne returns a record whose `id` field differs from the requested id (loose != comparison, so string '5' vs number 5 is fine); a buggy/fake dataProvider returning cached or default data; mapping responses so the id ends up under another key.

Common situations: Hand-rolled dataProviders that return { data: { ...record } } from a transformed response while losing the id; mocking providers returning a fixed record regardless of id; API responses keyed by uuid but code reads a numeric field; id normalization lost after JSON parsing.

Related errors


AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30). Data as JSON: /api/errors/2f73d89e1e2a8a7d. Report an issue: GitHub.