{"record":{"id":"084a06c771b91025","repo":"toeverything/AFFiNE","slug":"doc-default-role-can-not-be-owner","errorCode":"doc_default_role_can_not_be_owner","errorMessage":"Doc default role can not be owner.","messagePattern":"Doc default role can not be owner\\.","errorType":"http","errorClass":"DocDefaultRoleCanNotBeOwner","httpStatus":400,"severity":"error","filePath":"packages/backend/server/src/core/workspaces/resolvers/doc.ts","lineNumber":862,"sourceCode":"        workspaceId: input.workspaceId,\n        docId: input.docId,\n      });\n      this.logger.log(`Update doc user role (${JSON.stringify(info)})`);\n    }\n\n    return true;\n  }\n\n  @Mutation(() => Boolean)\n  async updateDocDefaultRole(\n    @CurrentUser() user: CurrentUser,\n    @Args('input') input: UpdateDocDefaultRoleInput\n  ) {\n    if (input.role === DocRole.Owner) {\n      this.logger.debug(\n        `Doc default role can not be owner (${JSON.stringify(input)})`\n      );\n      throw new DocDefaultRoleCanNotBeOwner();\n    }\n    const pairs = {\n      spaceId: input.workspaceId,\n      docId: input.docId,\n    };\n    if (input.workspaceId === input.docId) {\n      this.logger.error(\n        'Expect to update page default role, but it is a workspace',\n        pairs\n      );\n      throw new ExpectToUpdateDocUserRole(\n        pairs,\n        'Expect doc not to be workspace'\n      );\n    }\n    try {\n      await this.ac.user(user.id).doc(input).assert('Doc.Users.Manage');\n    } catch (error) {","sourceCodeStart":844,"sourceCodeEnd":880,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/workspaces/resolvers/doc.ts#L844-L880","documentation":"Thrown by updateDocDefaultRole when input.role === DocRole.Owner. The 'default role' is the role auto-applied to users who can reach the doc without an explicit grant; ownership is a singular, per-user capability (transfer/manage authority) and must never be a blanket default. Rejecting Owner up front (invalid_input) avoids creating docs where every reader is an owner.","triggerScenarios":"Calling mutation updateDocDefaultRole with UpdateDocDefaultRoleInput.role set to DocRole.Owner.","commonSituations":"A role picker component that lists all DocRole values is reused for the default-role selector; the enum is serialized by index and the highest index (Owner) is selected by default; a UI 'make everyone admin' shortcut mistakenly maps to Owner.","solutions":["Choose a non-owner DocRole for the default (Viewer, Commenter, or Editor).","Filter DocRole.Owner out of the default-role picker in the UI.","To grant ownership to a specific user, call updateDocUserRole with role: DocRole.Owner instead."],"exampleFix":"// before\nupdateDocDefaultRole({ workspaceId, docId, role: DocRole.Owner });\n// after\nupdateDocDefaultRole({ workspaceId, docId, role: DocRole.Editor });","handlingStrategy":"validation","validationCode":"function isValidDefaultRole(role: DocRole): boolean {\n  return role !== DocRole.Owner;\n}\nif (!isValidDefaultRole(input.role)) throw new Error('Default role cannot be Owner');","typeGuard":"function isNonOwnerRole(role: DocRole): boolean {\n  return role !== DocRole.Owner;\n}","tryCatchPattern":null,"preventionTips":["Exclude DocRole.Owner from default-role pickers.","Map 'make owner' to updateDocUserRole(role: Owner), not updateDocDefaultRole.","Serialize DocRole by name, not index, to avoid accidental Owner selection."],"tags":["graphql","permissions","validation","doc-role"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}