{"record":{"id":"6c8efc28bf236a5b","repo":"toeverything/AFFiNE","slug":"valuenotexists-6c8efc","errorCode":"ValueNotExists","errorMessage":"The overlay constructor '${this.name}' should have a static 'overlayName' property.","messagePattern":"The overlay constructor '(.+?)' should have a static 'overlayName' property\\.","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/affine/blocks/surface/src/renderer/overlay.ts","lineNumber":27,"sourceCode":"import type { RoughCanvas } from '../utils/rough/canvas.js';\nimport type { CanvasRenderer } from './canvas-renderer.js';\n\n/**\n * An overlay is a layer covered on top of elements,\n * can be used for rendering non-CRDT state indicators.\n */\nexport abstract class Overlay extends Extension {\n  static overlayName: string = '';\n\n  protected _renderer: CanvasRenderer | null = null;\n\n  constructor(protected gfx: GfxController) {\n    super();\n  }\n\n  static override setup(di: Container): void {\n    if (!this.overlayName) {\n      throw new BlockSuiteError(\n        ErrorCode.ValueNotExists,\n        `The overlay constructor '${this.name}' should have a static 'overlayName' property.`\n      );\n    }\n\n    di.addImpl(OverlayIdentifier(this.overlayName), this, [\n      GfxControllerIdentifier,\n    ]);\n  }\n\n  clear() {\n    this.refresh();\n  }\n\n  dispose() {}\n\n  refresh() {\n    if (this._renderer) {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/affine/blocks/surface/src/renderer/overlay.ts#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"Migrating from an ORM that auto-generates ids; forms submitting partial objects; fixture helper functions that forget to set the id field.","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"],"exampleFix":"// before\ntable.insert({ data: { name: 'x' } }); // keyField 'id' missing\n\n// after\ntable.insert({ data: { id: crypto.randomUUID(), name: 'x' } });","handlingStrategy":"validation","validationCode":"function withKey(table: { name: string; keyField: string }, data: Record<string, any>) {\n  const val = data[table.keyField];\n  if (val === undefined || val === null) {\n    throw new Error(`${table.name}: missing primary key '${table.keyField}'`);\n  }\n  return data;\n}\ntable.insert({ data: withKey(tableMeta, { id: crypto.randomUUID(), name: 'x' }) });","typeGuard":"null","tryCatchPattern":null,"preventionTips":["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"],"tags":["orm","database","primary-key","validation"],"backgroundTag":"missing-primary-key","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}