toeverything/AFFiNE · error · DocIsNotPublic

doc_is_not_public

doc_is_not_public

Error message

Doc is not public.

What it means

DocIsNotPublic, thrown by DocModel.unpublish() (doc.ts:590-601). unpublish is a guarded state transition: it first awaits isPublic(workspaceId, docId) (which reads the doc meta's public flag) and throws when the doc was never published or is already unpublished, before upserting meta with public: false and publishedAt: null.

Solutions

  1. Check the published state first (isPublic) and skip the call when not public - make unpublish idempotent at the call site
  2. Catch DocIsNotPublic and treat it as success when you only need the end state 'not published'
  3. Refresh the doc's public state in the UI when the badge disagrees with the server

Example fix

// before
await doc.unpublish(workspaceId, docId);

// after - idempotent unpublish
if (await doc.isPublic(workspaceId, docId)) {
  await doc.unpublish(workspaceId, docId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (await doc.isPublic(workspaceId, docId)) {
  await doc.unpublish(workspaceId, docId);
}

Try / catch

try {
  await doc.unpublish(workspaceId, docId);
} catch (e) {
  if (e instanceof DocIsNotPublic) return; // already unpublished - treat as success
  throw e;
}

Prevention

When it happens

Trigger: unpublish(workspaceId, docId) on a doc whose meta does not have public = true - never published, already unpublished (double call), or no meta row yet.

Common situations: Retried unpublish requests (double-click, network retry); UI showing a stale 'Published' badge; cleanup routines unpublishing every doc indiscriminately.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of toeverything/AFFiNE@2af30773ae (2026-08-18). Data as JSON: /api/errors/f0ccc1d2c826f5df. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/models/doc.ts:609

  /**
   * Publish a doc as public.
   */
  async publish(
    workspaceId: string,
    docId: string,
    mode: PublicDocMode = PublicDocMode.Page
  ) {
    return await this.upsertMeta(workspaceId, docId, {
      public: true,
      mode,
      publishedAt: new Date(),
    });
  }

  @Transactional()
  async unpublish(workspaceId: string, docId: string) {
    if (!(await this.isPublic(workspaceId, docId))) {
      throw new DocIsNotPublic();
    }

    return await this.upsertMeta(workspaceId, docId, {
      public: false,
      publishedAt: null,
    });
  }

  /**
   * Check if the doc is public.
   */
  async isPublic(workspaceId: string, docId: string) {
    const policy = await this.db.docAccessPolicy.findUnique({
      where: { workspaceId_docId: { workspaceId, docId } },
      select: { visibility: true, publicRole: true },
    });
    return policy?.visibility === 'public' && policy.publicRole === 'external';
  }

View on GitHub (pinned to 2af30773ae)