toeverything/AFFiNE · error
Param not a number
Error message
Param not a number: ${mode},${numbeToken.text} What it means
The PrimaryKeyShouldNotBeUpdated validator rejects update payloads that include the key field at all — any value, even an unchanged one. The primary key addresses rows inside the adapters' key maps, so mutating it mid-update could orphan data; updates must identify the row (where clause) and change only non-key fields.
Solutions
- Strip the key from the update payload: const { [keyField]: _, ...patch } = entity before validating/sending
- Separate insert vs update code paths so update always receives a partial patch plus the key in the where clause
- Add a dev-mode assertion that patch[table.keyField] === undefined
Example fix
// before
table.update({ where: { byKey: id }, data: entity }); // entity still contains id
// after
const { id: _key, ...patch } = entity;
table.update({ where: { byKey: id }, data: patch }); Defensive patterns
Strategy: validation
Validate before calling
function toPatch(keyField: string, entity: Record<string, any>) {
const { [keyField]: _drop, ...patch } = entity;
return patch;
}
table.update({ where: { byKey: id }, data: toPatch('id', entity) }); Type guard
null
Prevention
- Never pass a whole entity to update — strip the key field into a partial patch
- Keep insert and update paths separate; update identifies rows via where, changes only non-key fields
- Add a dev-mode assertion that the update payload has no key field
When it happens
Trigger: Passing a whole entity object including id to an update API instead of a partial patch; building the update payload with spread { ...entity, name: 'new' }; reusing an insert object as the update payload.
Common situations: REST-style handlers that PUT full objects; form state round-trips that carry ids; generic save() functions shared by insert and update paths.
Related errors
- ValueNotExists
- ValueNotExists
- A curve must have at least three points.
- Bad segment
- Path data ended short
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/04eadb34d3081fe8.
Report an issue: GitHub.
Appendix: source
Thrown at blocksuite/affine/blocks/surface/src/utils/path-data-parser/parser.ts:103
paramsCount = PARAMS[token.text];
mode = token.text;
} else {
return parsePath('M0,0' + d);
}
} else if (isType(token, NUMBER)) {
paramsCount = PARAMS[mode];
} else {
index++;
paramsCount = PARAMS[token.text];
mode = token.text;
}
if (index + paramsCount < tokens.length) {
for (let i = index; i < index + paramsCount; i++) {
const numbeToken = tokens[i];
if (isType(numbeToken, NUMBER)) {
params[params.length] = +numbeToken.text;
} else {
throw new Error(
'Param not a number: ' + mode + ',' + numbeToken.text
);
}
}
if (typeof PARAMS[mode] === 'number') {
const segment: Segment = { key: mode, data: params };
segments.push(segment);
index += paramsCount;
token = tokens[index];
if (mode === 'M') mode = 'L';
if (mode === 'm') mode = 'l';
} else {
throw new Error('Bad segment: ' + mode);
}
} else {
throw new Error('Path data ended short');
}
}View on GitHub (pinned to b4c8548c09)