facebook/relay · error
The __id field must be present on the argument. This indicat
Error message
The __id field must be present on the argument. This indicates a bug in Relay.
What it means
When assigning a singular linked field through an updatable proxy, the new value must carry a `__id` (data ID) so Relay can link the corresponding store record. A value without `__id` is not a valid record reference; Relay declares this an internal invariant violation.
Source
Thrown at packages/relay-runtime/mutations/createUpdatableProxy.js:257
);
}
};
}
function createSetterForSingularLinkedField(
selection: ReaderLinkedField,
variables: Variables,
updatableProxyRootRecord: RecordProxy,
recordSourceProxy: RecordSourceProxy,
) {
return function set(newValue: ?{__id: string, ...}) {
const newVariables = getArgumentValues(selection.args ?? [], variables);
if (newValue == null) {
updatableProxyRootRecord.setValue(newValue, selection.name, newVariables);
} else {
const {__id} = newValue;
if (__id == null) {
throw new Error(
'The __id field must be present on the argument. This indicates a bug in Relay.',
);
}
const newValueRecord = recordSourceProxy.get(__id);
if (newValueRecord == null) {
throw new Error(`Did not find item with data id ${__id} in the store.`);
}
updatableProxyRootRecord.setLinkedRecord(
newValueRecord,
selection.name,
newVariables,
);
}
};
}
function createGetterForPluralLinkedField(
selection: ReaderLinkedField,View on GitHub (pinned to 668b1b85e0)
Solutions
- Assign records obtained via `updatable.<field>.get()` or `store.get(id)` — never raw payload objects
- If you have a data ID, do `store.get(id)` first and set the returned record
- Copy needed fields from the raw object into a store record, then assign that record
- If a genuine RecordProxy lacks `__id`, report it as a Relay bug
Example fix
// before updatable.viewer.bestFriend.set(response.updateUser.bestFriend); // raw object // after const friend = store.get(response.updateUser.bestFriend.id); updatable.viewer.bestFriend.set(friend);
Defensive patterns
Strategy: type-guard
Validate before calling
function isRecordProxyLike(v) {
return v != null && typeof v === 'object' && typeof v.__id === 'string' && v.__id.length > 0;
}
if (next != null && !isRecordProxyLike(next)) throw new TypeError('Singular setter requires a record proxy with __id'); Type guard
function isRecordRef(v: unknown): v is {__id: string} {
return typeof v === 'object' && v !== null && typeof (v as any).__id === 'string';
} Try / catch
try {
field.set(next);
} catch (e) {
if (e.message.includes('__id field must be present')) throw new Error('Assign store records, not raw payload objects', {cause: e});
throw e;
} Prevention
- Assign only records from updatable proxies or store.get(id)
- Never pass inline object literals or raw responses to linked field setters
- Convert payloads to store records before linking
- TypeScript: type setter args as the proxy type so raw objects fail compilation
When it happens
Trigger: Calling `singularField.set(value)` with a raw object (e.g. a mutation response payload or inline object literal) that has no `__id`, instead of a record proxy from the store/updatable proxy.
Common situations: Assigning raw GraphQL response data directly in an updater; constructing `set({...})` with object literals; TypeScript types not narrowing away plain objects.
Related errors
- The __id field must be present on each item passed to the se
- Do not assign null to plural linked fields; assign an empty
- When assigning an array of items, none of the items should b
- BabelPluginRelay: Expected exactly one definition per graphq
- BabelPluginRelay: Expected a fragment, mutation, query, or s
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/4c42f49162638b8c.
Report an issue: GitHub.