marmelab/react-admin · error · Error

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

Error message

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

What it means

useEditController (used internally by <Edit> / useEditController) fetches a single record by the id taken from the route/props. After the data provider returns, it checks that the fetched record's own `id` attribute equals the requested id (loose equality). If the data provider returned a record with a different id, react-admin throws because rendering an edit form for the wrong record would silently corrupt data.

Source

Thrown at packages/ra-core/src/controller/edit/useEditController.ts:147

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

    // eslint-disable-next-line eqeqeq
    if (record && record.id && record.id != id) {
        throw new Error(
            `useEditController: 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.edit`, {
        id,
        record,
        recordRepresentation:
            typeof recordRepresentation === 'string'
                ? recordRepresentation
                : '',
        _: translate('ra.page.edit', {
            name: getResourceLabel(resource, 1),
            id,
            record,
            recordRepresentation:

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Fix the dataProvider's getOne so it returns exactly the record whose id was requested (verify the backend endpoint honors the :id parameter).
  2. Ensure the backend lookup key matches the id react-admin passes (check the route param / id parsing, e.g. parseInt on numeric ids).
  3. Check test fixtures / mocked getOne responses return a record with the same id that the component requests.
  4. Confirm you are not reusing an <Edit> or useEditController instance across resources without setting the correct `resource` prop.

Example fix

// before: dataProvider ignores the requested id
getOne: (resource, params) => fetch(`${apiUrl}/${resource}`).then(...)
// after: request the specific record by id
getOne: (resource, params) =>
  fetch(`${apiUrl}/${resource}/${params.id}`).then(...)
Defensive patterns

Strategy: validation

Validate before calling

// validate what the dataProvider will return for this id before rendering Edit
const record = await dataProvider.getOne(resource, { id }).then(r => r.data);
if (record?.id != null && String(record.id) !== String(id)) {
  throw new Error(`dataProvider returned record id ${record.id} for requested id ${id}`);
}

Type guard

const isRecordForId = (record, id) =>
  record != null && record.id != null && String(record.id) === String(id);

Try / catch

try {
  render(<Edit id={id} resource={resource} />);
} catch (e) {
  if (String(e.message).includes("must match the requested 'id'")) {
    // report dataProvider bug / reload record
  } else throw e;
}

Prevention

When it happens

Trigger: Calling useEditController (or <Edit>) where the query for `id` returns a record whose `record.id` differs, e.g. a misconfigured dataProvider that ignores the requested id (getOne returning a cached or first record), a backend that looks up by another key, or string-vs-number routing ids resolved against the wrong resource.

Common situations: Custom dataProviders that cache aggressively and return the most recent record regardless of id; backends whose GET /posts/:id endpoint ignores the :id param and returns a default document; copying an <Edit> component between resources without changing the resource prop so the provider resolves a record from another table; tests mocking getOne with a hardcoded record id.

Related errors


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