toeverything/AFFiNE · error · BlockSuiteError
ValueNotExists
ValueNotExists
Error message
The overlay constructor '${this.name}' should have a static 'overlayName' property. What it means
The PrimaryKeyShouldExist data validator runs on write operations and requires data[table.keyField] to be neither undefined nor null. Without a key the row would be unaddressable in the adapter's key map, so the validator rejects the payload naming the table and the exact key field that is missing.
Solutions
- Set the primary key before insert — generate one explicitly (crypto.randomUUID()) if the schema has no generator
- Move key generation into the repository layer right before insert so no caller can forget it
- In dev builds, assert payload[table.keyField] != null before writing to fail with your own context
Example fix
// before
table.insert({ data: { name: 'x' } }); // keyField 'id' missing
// after
table.insert({ data: { id: crypto.randomUUID(), name: 'x' } }); Defensive patterns
Strategy: validation
Validate before calling
function withKey(table: { name: string; keyField: string }, data: Record<string, any>) {
const val = data[table.keyField];
if (val === undefined || val === null) {
throw new Error(`${table.name}: missing primary key '${table.keyField}'`);
}
return data;
}
table.insert({ data: withKey(tableMeta, { id: crypto.randomUUID(), name: 'x' }) }); Type guard
null
Prevention
- Generate the primary key explicitly (crypto.randomUUID()) at the repository layer before insert
- Never rely on null/undefined meaning auto-generate — this ORM requires a concrete key
- Assert payload[keyField] != null in dev builds to fail fast with your own context
When it happens
Trigger: table.insert({ data: { name: 'x' } }) when the schema's keyField is 'id' but the payload omits it; the key is generated asynchronously and the insert was not awaited in order; the id field is explicitly set to null hoping for auto-generation (this ORM does not auto-generate in this path); spreading an object that never contained the key.
Common situations: Migrating from an ORM that auto-generates ids; forms submitting partial objects; fixture helper functions that forget to set the id field.
Related errors
- Param not a number
- 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/6c8efc28bf236a5b.
Report an issue: GitHub.
Appendix: source
Thrown at blocksuite/affine/blocks/surface/src/renderer/overlay.ts:27
import type { RoughCanvas } from '../utils/rough/canvas.js';
import type { CanvasRenderer } from './canvas-renderer.js';
/**
* An overlay is a layer covered on top of elements,
* can be used for rendering non-CRDT state indicators.
*/
export abstract class Overlay extends Extension {
static overlayName: string = '';
protected _renderer: CanvasRenderer | null = null;
constructor(protected gfx: GfxController) {
super();
}
static override setup(di: Container): void {
if (!this.overlayName) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
`The overlay constructor '${this.name}' should have a static 'overlayName' property.`
);
}
di.addImpl(OverlayIdentifier(this.overlayName), this, [
GfxControllerIdentifier,
]);
}
clear() {
this.refresh();
}
dispose() {}
refresh() {
if (this._renderer) {View on GitHub (pinned to b4c8548c09)