{"record":{"id":"fee47d0ead93982b","repo":"Budibase/budibase","slug":"unable-to-un-assign-roles-license-required","errorCode":null,"errorMessage":"Unable to un-assign roles - license required.","messagePattern":"Unable to un-assign roles - license required\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/pro/src/sdk/publicApi/roles.ts","lineNumber":51,"sourceCode":"    }\n    if (opts.builder) {\n      user.builder = {\n        global: true,\n      }\n    }\n    if (opts.admin) {\n      user.admin = {\n        global: true,\n      }\n    }\n    user.roles\n  }\n  await userDB.bulkUpdate(users)\n}\n\nexport async function unAssign(userIds: string[], opts: AssignmentOpts) {\n  if (!(await isExpandedPublicApiEnabled())) {\n    throw new Error(\"Unable to un-assign roles - license required.\")\n  }\n  const users = await userDB.bulkGet(userIds)\n  for (let user of users) {\n    if (opts.role) {\n      const prodWorkspaceId = dbCore.getProdWorkspaceID(opts.role?.appId)\n      if (user.roles[prodWorkspaceId] === opts.role.roleId) {\n        delete user.roles[prodWorkspaceId]\n      }\n    }\n    if (opts.appBuilder && user.builder?.apps) {\n      const prodWorkspaceId = dbCore.getProdWorkspaceID(opts.appBuilder.appId)\n      user.builder.apps = user.builder.apps.filter(\n        appId => appId !== prodWorkspaceId\n      )\n    }\n    if (opts.builder && user.builder) {\n      delete user.builder\n    }","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/pro/src/sdk/publicApi/roles.ts#L33-L69","documentation":"The counterpart to roles.assign, roles.unAssign is also gated behind the license-gated 'expanded public API' feature. If isExpandedPublicApiEnabled() returns false for the tenant, the call throws before reading users. The message distinguishes it from the assign variant so logs show which direction of role assignment was refused.","triggerScenarios":"Calling roles.unAssign (removing a role from users via the public API) on a tenant without the expanded public API entitlement; expired license causing the feature check to fail.","commonSituations":"Automation scripts revoking app roles via public REST API on a free/self-host tier; license downgrade removing the add-on mid-integration; cached license state stale after upgrade so flag still reads disabled.","solutions":["Upgrade the tenant's license to include expanded public API access","Force a license re-check/re-activation so the feature flag updates","Perform role un-assignment via the builder UI or internal SDK instead of the public API","Catch this error in integrations and prompt the user about the missing entitlement"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const enabled = await isExpandedPublicApiEnabled()\nif (!enabled) throw new Error(\"Expanded public API requires a license upgrade\")","typeGuard":null,"tryCatchPattern":"try {\n  await roles.unAssign(userIds, opts)\n} catch (err: any) {\n  if (err.message === \"Unable to un-assign roles - license required.\") {\n    // fall back to builder UI / internal API\n  } else { throw err }\n}","preventionTips":["Gate integrations on the expanded public API entitlement","Re-check the feature flag after license changes/downgrades","Provide admins an internal path for role management"],"tags":["licensing","public-api","roles","feature-flag"],"backgroundTag":"license-required","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}