toeverything/AFFiNE · error · DocNotFound

doc_not_found

doc_not_found

Error message

Doc ${docId} under Space ${spaceId} not found.

What it means

Thrown by the sync WebSocket gateway when a client requests a doc diff (the 'space:diff-doc-update' handler) and the underlying DocStorageAdapter.diff() resolves to a falsy value, meaning no document with that guid exists in the given space. It fires only after permission and room-membership checks pass, so it indicates a genuinely missing document rather than an access problem. The docId is parsed into a DocID so the lookup uses the guid portion; a stale or wrong guid will surface here.

Source

Thrown at packages/backend/server/src/core/sync/gateway.ts:672

    const adapter = this.selectAdapter(client, spaceType);
    adapter.assertIn(spaceId);
    this.assertUserdataSubject(spaceType, user.id, spaceId, id.guid);
    await this.assertDocActionAllowed(
      spaceType,
      user.id,
      spaceId,
      id.guid,
      'Doc.Read'
    );

    const doc = await adapter.diff(
      spaceId,
      id.guid,
      stateVector ? Buffer.from(stateVector, 'base64') : undefined
    );

    if (!doc) {
      throw new DocNotFound({ spaceId, docId });
    }

    return {
      data: {
        missing: Buffer.from(doc.missing).toString('base64'),
        state: Buffer.from(doc.state).toString('base64'),
        timestamp: doc.timestamp,
      },
    };
  }

  @SubscribeMessage('space:delete-doc')
  async onDeleteSpaceDoc(
    @ConnectedSocket() client: Socket,
    @CurrentUser() user: CurrentUser,
    @MessageBody() { spaceType, spaceId, docId }: DeleteDocMessage
  ): Promise<EventResponse<{ success: true }>> {
    const adapter = this.selectAdapter(client, spaceType);

View on GitHub (pinned to 26c515e050)

Solutions

  1. Verify the docId guid actually exists by calling getSpaceDocTimestamps / a doc-list call before diffing.
  2. Treat doc_not_found as a signal to remove the doc from the local cache and stop retrying the diff for that guid.
  3. If the doc was expected, check the server logs/storage to confirm whether 'space:delete-doc' or a migration removed it.
  4. Ensure the client is not generating synthetic docIds locally — ids must originate from the server or a real create flow.

Example fix

// before — blindly diffing a cached id
socket.emit('space:diff-doc-update', { spaceType, spaceId, docId, stateVector });

// after — drop local doc on doc_not_found and stop syncing it
try {
  await socket.emitWithAck('space:diff-doc-update', { spaceType, spaceId, docId, stateVector });
} catch (e) {
  if (e.code === 'doc_not_found') {
    localCache.removeDoc(spaceId, docId);
    return;
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the doc exists before diffing
const timestamps = await socket.emitWithAck('space:get-doc-timestamps', { spaceType, spaceId });
if (!(docId in timestamps)) { /* skip diff */ }

Type guard

function isKnownDocId(spaceTimestamps: Record<string, number>, docId: string): boolean {
  return docId in spaceTimestamps;
}

Try / catch

try {
  const diff = await socket.emitWithAck('space:diff-doc-update', payload);
  applyDiff(diff);
} catch (e) {
  if (e?.code === 'doc_not_found') { localCache.removeDoc(spaceId, docId); return; }
  throw e;
}

Prevention

When it happens

Trigger: Client emits 'space:diff-doc-update' with { spaceType, spaceId, docId, stateVector } where the guid extracted from docId has no row in the doc storage for that spaceId. Also occurs when the doc was deleted by another peer between the client learning of it and requesting the diff, or when a client sends a locally-generated/temporary docId that was never persisted.

Common situations: Client holds a cached docId from an old session after the doc was deleted server-side; race between 'space:delete-doc' and a pending diff; docId typo or copy across spaces; fresh deployment where the doc was never synced because the client fabricated the id locally.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/0aea39ea574d0985. Report an issue: GitHub.