{"record":{"id":"fc3875752d50d783","repo":"toeverything/AFFiNE","slug":"valuenotexists-fc3875","errorCode":"ValueNotExists","errorMessage":"Key is not defined in the EdgelessClipboardConfig","messagePattern":"Key is not defined in the EdgelessClipboardConfig","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/affine/blocks/surface/src/extensions/clipboard-config.ts","lineNumber":65,"sourceCode":"    index?: number\n  ) => {\n    const block = await this.std.clipboard.pasteBlockSnapshot(\n      snapshot,\n      doc,\n      parent,\n      index\n    );\n    return block?.id ?? null;\n  };\n\n  abstract createBlock(\n    snapshot: BlockSnapshot,\n    context: ClipboardConfigCreationContext\n  ): string | null | Promise<string | null>;\n\n  static override setup(di: Container) {\n    if (!this.key) {\n      throw new BlockSuiteError(\n        BlockSuiteError.ErrorCode.ValueNotExists,\n        'Key is not defined in the EdgelessClipboardConfig'\n      );\n    }\n\n    di.add(\n      this as unknown as { new (std: BlockStdScope): EdgelessClipboardConfig },\n      [StdIdentifier]\n    );\n\n    di.addImpl(EdgelessClipboardConfigIdentifier(this.key), provider =>\n      provider.get(this)\n    );\n  }\n}\n","sourceCodeStart":47,"sourceCodeEnd":81,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/affine/blocks/surface/src/extensions/clipboard-config.ts#L47-L81","documentation":"The in-memory table adapter enforces primary-key uniqueness at insert time: it stringifies data[keyField] and rejects the insert when that key already exists in the table's map, mirroring a database UNIQUE constraint. This makes duplicate-key bugs surface deterministically in tests and memory-backed runs instead of silently overwriting the earlier row.","triggerScenarios":"Inserting the same entity key twice (retry after an error, double submit, duplicate import); fixture/setup code running per test against a shared memory DB without clearing; keys generated non-uniquely (Math.random collisions, fixed ids); using insert where an update/upsert was intended.","commonSituations":"Test seeds accumulating across runs; client double-clicks and idempotency gaps; auto-generated ids not unique across workers or sessions.","solutions":["If the row may already exist, check first with find({ where: { [keyField]: key } }) and update() instead of insert()","Generate genuinely unique keys (crypto.randomUUID or a monotonic counter) instead of fixed or low-entropy ids","Reset/recreate the memory DB between test cases so seeded keys do not carry over"],"exampleFix":"// before\ntable.insert({ data: { id: 'a1', name: 'x' } });\ntable.insert({ data: { id: 'a1', name: 'x' } }); // Record with key a1 already exists\n\n// after\nconst existing = table.find({ where: { byKey: 'a1' } });\nif (existing.length > 0) {\n  table.update({ where: { byKey: 'a1' }, data: { name: 'x' } });\n} else {\n  table.insert({ data: { id: crypto.randomUUID(), name: 'x' } });\n}","handlingStrategy":"validation","validationCode":"function upsert(table: TableAdapter, keyField: string, data: Record<string, any>) {\n  const key = String(data[keyField]);\n  const exists = table.find({ where: { byKey: key } }).length > 0;\n  if (exists) {\n    return table.update({ where: { byKey: key }, data });\n  }\n  return table.insert({ data });\n}","typeGuard":"null","tryCatchPattern":null,"preventionTips":["Check existence with find({ where: { byKey } }) before insert, or use a find-then-update upsert helper","Generate keys with crypto.randomUUID() instead of fixed or low-entropy values","Reset memory-backed tables between tests so seeded keys cannot accumulate","Make write paths idempotent on the client (disable double submit)"],"tags":["orm","database","primary-key","duplicate","in-memory"],"backgroundTag":"duplicate-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"}