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
- Fix the dataProvider getOne so the returned data.id equals the requested id
- Ensure the id key is named `id` in the returned record (or map your API key, e.g. _id → id)
- 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
- Map your API's id key (_id, uuid) to `id` in the dataProvider
- Unit-test getOne returns the exact record for each id
- Never return a fallback/default record from getOne
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
- useEditController: Fetched record's id attribute (${record.i
- create is not implemented
- delete not implemented
- deleteMany is not implemented
- getList is not implemented
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/2f73d89e1e2a8a7d.
Report an issue: GitHub.