marmelab/react-admin · error · Error

DatagridRow expects an id prop

Error message

DatagridRow expects an id prop

What it means

Inside <Datagrid>, each row (DatagridRow) needs the record id to build selection state, row click handlers, and expansion keys. The expand-content variant of DatagridRow destructures `id` from props and throws immediately when it is undefined, since rows without ids cannot participate in the datagrid's row identity logic.

Source

Thrown at packages/ra-ui-materialui/src/list/datagrid/DatagridRow.tsx:60

> = React.forwardRef<HTMLTableRowElement, DatagridRowProps>((props, ref) => {
    const {
        children,
        className,
        expand,
        hasBulkActions = false,
        hover = true,
        id,
        onToggleItem,
        record: recordOverride,
        rowClick,
        selected = false,
        style,
        selectable = true,
        ...rest
    } = props;

    if (typeof id === 'undefined') {
        throw new Error('DatagridRow expects an id prop');
    }
    const context = useDatagridContext();
    const translate = useTranslate();
    const record = useRecordContext(props);
    if (!record) {
        throw new Error(
            'DatagridRow can only be used within a RecordContext or be passed a record prop'
        );
    }
    const resource = useResourceContext(props);
    const resourceDefinition = useResourceDefinition(props);
    const hasDetailView =
        resourceDefinition.hasShow || resourceDefinition.hasEdit;
    if (!resource) {
        throw new Error(
            'DatagridRow can only be used within a ResourceContext or be passed a resource prop'
        );
    }

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Forward all row props to DatagridRow, including id: `<DatagridRow {...props} />`.
  2. When using DatagridRow directly, pass `id={record.id}`.
  3. In custom wrappers, explicitly destructure and re-pass `id`.

Example fix

// before
const MyRow = ({ id, ...rest }) => <DatagridRow {...rest} />;
// after
const MyRow = (props) => <DatagridRow {...props} />;
Defensive patterns

Strategy: type-guard

Validate before calling

rows.forEach(r => { if (r.id == null) throw new Error('dataProvider returned a row without id'); });

Type guard

const hasId = (r: Record<string, unknown> & { id?: unknown }): r is { id: Identifier } =>
  r.id !== undefined && r.id !== null;

Prevention

When it happens

Trigger: Rendering a custom row component (row via `<Datagrid row={...}>` or expand panel) that does not forward the `id` prop down to DatagridRow, or using DatagridRow directly without an id.

Common situations: Wrapping DatagridRow in a custom component that filters out unknown props (including id); building a custom expand renderer and forgetting `{...props}` passthrough; TypeScript not catching it because props were spread loosely.

Related errors


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