toeverything/AFFiNE · warning · Error

No metadata provided

Error message

No metadata provided

What it means

Plain Error thrown by updateDocMeta when called with meta.title === undefined. The method's only supported field is title, so an input without it is a no-op at best and almost always a caller bug. It is a generic Error (not BadRequest), so it will surface as 500 unless wrapped — a defect worth fixing in the library.

Source

Thrown at packages/backend/server/src/core/doc/writer.ts:216

    return { success: true };
  }

  /**
   * Updates document metadata (currently title only).
   *
   * @param workspaceId - The workspace ID
   * @param docId - The document ID to update
   * @param meta - Metadata updates
   * @param editorId - Optional editor ID for tracking
   */
  async updateDocMeta(
    workspaceId: string,
    docId: string,
    meta: { title?: string },
    editorId?: string
  ): Promise<UpdateDocResult> {
    if (meta.title === undefined) {
      throw new Error('No metadata provided');
    }

    this.logger.debug(`Updating doc meta ${docId} in workspace ${workspaceId}`);

    const existingDoc = await this.storage.getDoc(workspaceId, docId);
    if (!existingDoc?.bin) {
      throw new NotFoundException(`Document ${docId} not found`);
    }

    const rootDoc = await this.storage.getDoc(workspaceId, workspaceId);
    if (!rootDoc?.bin) {
      throw new NotFoundException(
        `Workspace ${workspaceId} not found or has no root document`
      );
    }

    const existingBinary = Buffer.isBuffer(existingDoc.bin)
      ? existingDoc.bin

View on GitHub (pinned to 26c515e050)

Solutions

  1. On the caller, only invoke updateDocMeta when meta.title !== undefined; skip the call entirely otherwise.
  2. If title is the only field, prefer a dedicated setTitle method or require title as a positional arg so the type system rejects `{}`.
  3. In the library, replace `throw new Error('No metadata provided')` with `throw new BadRequest('No metadata provided')` so it returns 400, not 500.

Example fix

// before
async updateDocMeta(workspaceId, docId, meta: { title?: string }, editorId?) {
  if (meta.title === undefined) {
    throw new Error('No metadata provided');
  }
  ...
}

// after — make the contract explicit and return 400
async updateDocMeta(workspaceId, docId, title: string, editorId?) {
  if (typeof title !== 'string' || title.length === 0) {
    throw new BadRequest('title is required for updateDocMeta');
  }
  ...
}
Defensive patterns

Strategy: validation

Validate before calling

function buildMetaUpdate(input: { title?: string }) {
  if (input.title === undefined) return null; // nothing to do — skip the call
  return { title: input.title };
}

const meta = buildMetaUpdate(form);
if (meta) await writer.updateDocMeta(ws, doc, meta);

Type guard

function hasMetaTitle(meta: unknown): meta is { title: string } {
  return typeof (meta as any)?.title === 'string';
}

Try / catch

if (hasMetaTitle(form)) {
  await writer.updateDocMeta(ws, doc, { title: form.title });
} // else skip — never trigger the error

Prevention

When it happens

Trigger: Caller passes `{}` or omits title, e.g. `updateDocMeta(ws, doc, {})` or `updateDocMeta(ws, doc, { someOtherField: x })`. Often a frontend that builds the meta object conditionally and ends up with no keys.

Common situations: Frontend form where the title field was unchanged and the build-meta helper skipped it. A refactor that renamed the field but left old callers. Batch job iterating over objects that happen to have no title key.

Related errors


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