{"record":{"id":"306d1cabe7063a67","repo":"toeverything/AFFiNE","slug":"document-docid-not-found","errorCode":null,"errorMessage":"Document ${docId} not found","messagePattern":"Document (.+?) not found","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"packages/backend/server/src/core/doc/writer.ts","lineNumber":166,"sourceCode":"   * @param workspaceId - The workspace ID\n   * @param docId - The document ID to update\n   * @param markdown - The new markdown content\n   * @param editorId - Actor user ID\n   */\n  async updateDoc(\n    workspaceId: string,\n    docId: string,\n    markdown: string,\n    editorId: string\n  ): Promise<UpdateDocResult> {\n    this.logger.debug(\n      `Updating doc ${docId} in workspace ${workspaceId} from markdown`\n    );\n\n    // Fetch existing document\n    const existingDoc = await this.storage.getDoc(workspaceId, docId);\n    if (!existingDoc?.bin) {\n      throw new NotFoundException(`Document ${docId} not found`);\n    }\n\n    // Compute delta update using structural diff\n    // Use zero-copy buffer view when possible for native function\n    const existingBinary = Buffer.isBuffer(existingDoc.bin)\n      ? existingDoc.bin\n      : Buffer.from(\n          existingDoc.bin.buffer,\n          existingDoc.bin.byteOffset,\n          existingDoc.bin.byteLength\n        );\n    const delta = updateDocWithMarkdown(existingBinary, markdown, docId);\n\n    // Push only the delta changes\n    const timestamp = await this.storage.pushDocUpdates(\n      workspaceId,\n      docId,\n      [delta],","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/2af30773aecd567f09b346e7b72fc69143144057/packages/backend/server/src/core/doc/writer.ts#L148-L184","documentation":"DocWriter.updateDoc fetches the existing doc binary from storage to compute a structural markdown diff (updateDocWithMarkdown). If getDoc returns no bin for (workspaceId, docId) it throws Nest NotFoundException (HTTP 404) with the docId in the message — the target of the update does not exist.","triggerScenarios":"Updating a doc that was deleted in another session; passing a client-generated/temporary docId that was never persisted; wrong workspaceId so the (workspaceId, docId) pair matches nothing; doc created only locally by the client but never synced.","commonSituations":"Stale editor state after a doc is moved or deleted; import pipelines re-running against a cleaned database; copy-pasted docIds between environments (dev vs prod).","solutions":["Verify the (workspaceId, docId) pair via a doc read API before updating","If the doc is genuinely missing, call createDoc instead of updateDoc","Refresh the client's doc list to drop deleted ids","Make sure the environment/db the writer targets is the one where the doc lives"],"exampleFix":"// before\nawait docWriter.updateDoc(wsId, docId, markdown);\n\n// after\nconst existing = await storage.getDoc(wsId, docId);\nif (!existing?.bin) {\n  return docWriter.createDoc(wsId, title, markdown); // or surface 404 to caller\n}\nawait docWriter.updateDoc(wsId, docId, markdown);","handlingStrategy":"validation","validationCode":"const existing = await storage.getDoc(workspaceId, docId);\nif (!existing?.bin) {\n  return docWriter.createDoc(workspaceId, title, markdown); // upsert-style fallback\n}\nawait docWriter.updateDoc(workspaceId, docId, markdown);","typeGuard":"function isDocMissing404(e: unknown): boolean {\n  const err = e as { status?: number; message?: string; response?: { status?: number } };\n  return (err.response?.status === 404 || err.status === 404) && /not found/i.test(err.message ?? '');\n}","tryCatchPattern":"try {\n  await docWriter.updateDoc(wsId, docId, markdown);\n} catch (e) {\n  if (isDocMissing404(e)) return handleDocDeleted(docId); // refresh list / recreate\n  throw e;\n}","preventionTips":["Read-before-write: confirm the (workspaceId, docId) pair exists before updating","Use server-provided docIds; never synthesize them client-side","Drop deleted doc ids from local caches on 404"],"tags":["doc-writer","doc","not-found","markdown-import"],"backgroundTag":"entity-not-found","analyzedSha":"2af30773aecd567f09b346e7b72fc69143144057","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}