toeverything/AFFiNE · error · BadRequestException

description must be provided explicitly.

Error message

description must be provided explicitly.

What it means

Input contract check in the BYOK resolver: updating a workspace BYOK profile requires the description field to be present in the mutation input — explicitly, even when the intent is to clear it (description: null). requireExplicitDescription uses Object.hasOwn(input, 'description'), so omitting the key entirely (as many GraphQL clients do for unchanged fields) throws BadRequestException instead of silently leaving description untouched.

Solutions

  1. Always include description in the update input — pass its current value to keep it, or null to clear it.
  2. If your GraphQL client prunes nulls, configure it to preserve explicit nulls for this mutation (e.g. omitNull: false in apollo-client v3 composites) or build the input literal manually.
  3. On the server, consider splitting into explicit update paths if clients cannot express 'field absent' vs 'field null'.

Example fix

# before
mutation { updateByokProfile(workspaceId: "ws", input: { name: "gpt4" }) }

# after — description present; null clears it explicitly
mutation { updateByokProfile(workspaceId: "ws", input: { name: "gpt4", description: null }) }
Defensive patterns

Strategy: validation

Validate before calling

// Explicitly control field presence before sending the update
const input: WorkspaceByokProfileDefinitionInput & { description: string | null } = {
  ...patch,
  description: 'description' in patch ? patch.description : currentProfile.description,
};

Type guard

const hasExplicitDescription = (
  input: object
): input is { description: string | null } =>
  Object.hasOwn(input, 'description');

Try / catch

try {
  await updateByokProfile({ workspaceId, input });
} catch (e) {
  if (/description must be provided explicitly/i.test(String(e?.message))) {
    return updateByokProfile({ workspaceId, input: { ...input, description: input.description ?? null } });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling updateByokProfile (or equivalent) with the description field omitted; GraphQL clients that strip null/unset fields before sending; code paths building the input via spread of a partial object where description was never set; auto-generated clients dropping optional fields.

Common situations: Frontend forms that only send changed fields; Apollo/urql normalized updates pruning nulls; scripts PATCHing only the fields they modify; client generated from schema marking description optional and omitting it.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at packages/backend/server/src/plugins/copilot/byok/resolver.ts:713

      userId: user.id,
    });
    return {
      leaseId: result.leaseId,
      expiresAt: new Date(result.expiresAtMs),
    };
  }

  private async assertUpdate(userId: string, workspaceId: string) {
    await this.ac
      .user(userId)
      .workspace(workspaceId)
      .assert('Workspace.Settings.Update');
  }
}

function requireExplicitDescription(input: { description: string | null }) {
  if (!Object.hasOwn(input, 'description')) {
    throw new BadRequestException('description must be provided explicitly.');
  }
}

function nativeDefinition(input: WorkspaceByokProfileDefinitionInput) {
  return {
    ...input,
    endpoint: {
      ...input.endpoint,
      url: input.endpoint.url ?? undefined,
      dialect: input.endpoint.dialect ?? undefined,
    },
  };
}

function projectProbe(probe: {
  kind: string;
  testedAtMs?: number;
  errorKind?: string;

View on GitHub (pinned to 2af30773ae)