{"record":{"id":"f2dbb2e1052e2cf1","repo":"twentyhq/twenty","slug":"partner-role-not-found-available-roles-labels","errorCode":null,"errorMessage":"Partner role not found. Available roles: ${labels}. Ensure the app is installed (universalIdentifier=${PARTNER_ROLE_UNIVERSAL_IDENTIFIER}).","messagePattern":"Partner role not found\\. Available roles: (.+?)\\. Ensure the app is installed \\(universalIdentifier=(.+?)\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-apps/internal/twenty-partners/src/scripts/configure-partner-rls.ts","lineNumber":389,"sourceCode":"  // Fetching fieldPermissions here avoids a second getRoles call later in step 5.\n  const rolesData = await metadataFetch<{\n    getRoles: {\n      id: string;\n      label: string;\n      fieldPermissions: FieldPermissionResult[];\n    }[];\n  }>(\n    metadataUrl,\n    apiKey,\n    `{ getRoles { id label fieldPermissions { id fieldMetadataId objectMetadataId canUpdateFieldValue canReadFieldValue } } }`,\n  );\n\n  const roles = rolesData.getRoles;\n  const partnerRole = roles.find((r) => r.label === PARTNER_ROLE_LABEL);\n\n  if (!partnerRole) {\n    const labels = roles.map((r) => r.label).join(', ');\n    throw new Error(\n      `Partner role not found. Available roles: ${labels}. ` +\n        `Ensure the app is installed (universalIdentifier=${PARTNER_ROLE_UNIVERSAL_IDENTIFIER}).`,\n    );\n  }\n\n  console.log(\n    `[rls:configure] Partner role id: ${partnerRole.id} ` +\n      `(universalIdentifier in manifest: ${PARTNER_ROLE_UNIVERSAL_IDENTIFIER})`,\n  );\n\n  // ── 4. Upsert one predicate per object ───────────────────────────────────────\n  //\n  // \"the record's partnerUser relation IS the current workspace member\". Operand must be IS,\n  // not CONTAINS: the upsert accepts CONTAINS but the RELATION query filter only allows\n  // IS / IS_NOT and throws \"Unknown operand CONTAINS for RELATION filter\" at query time.\n  // value stays null; workspaceMemberFieldMetadataId injects the current member at query time.\n\n  const MUTATION = `","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-apps/internal/twenty-partners/src/scripts/configure-partner-rls.ts#L371-L407","documentation":"configure-partner-rls fetches all roles and finds the one whose label equals PARTNER_ROLE_LABEL (the role shipped by the app manifest). If none matches, it throws listing the available role labels and the app's universalIdentifier. The Partner role must exist before the script can attach RLS predicates to it.","triggerScenarios":"getRoles returns a list with no role.label === PARTNER_ROLE_LABEL. Causes: the app isn't installed (the role comes from the manifest); the app is installed but roles haven't synced; the role label was changed; querying the wrong workspace; the manifest's universalIdentifier doesn't match PARTNER_ROLE_UNIVERSAL_IDENTIFIER.","commonSituations":"Running rls:configure before/without installing the app; partial install where objects synced but roles didn't; wrong workspace; app version that renamed the role; manually deleted the Partner role.","solutions":["Install/re-sync the partners app so its PARTNER_ROLE lands in the workspace (the message prints the expected universalIdentifier).","Confirm TWENTY_PARTNERS_API_URL/TWENTY_PARTNERS_API_KEY point at the correct workspace.","Compare the printed 'Available roles' against PARTNER_ROLE_LABEL to catch a rename.","Re-run rls:configure after the role appears (idempotent)."],"exampleFix":"// before\nif (!partnerRole) {\n  const labels = roles.map((r) => r.label).join(', ');\n  throw new Error(`Partner role not found. Available roles: ${labels}. Ensure the app is installed (universalIdentifier=${PARTNER_ROLE_UNIVERSAL_IDENTIFIER}).`);\n}\n\n// after — also match by universalIdentifier as a fallback and report both\nconst partnerRole =\n  roles.find((r) => r.label === PARTNER_ROLE_LABEL) ??\n  roles.find((r) => r.universalIdentifier === PARTNER_ROLE_UNIVERSAL_IDENTIFIER);\nif (!partnerRole) {\n  const labels = roles.map((r) => `${r.label}(${r.universalIdentifier ?? 'no-uid'})`).join(', ');\n  throw new Error(`Partner role not found (label=${PARTNER_ROLE_LABEL}, uid=${PARTNER_ROLE_UNIVERSAL_IDENTIFIER}). Available roles: ${labels}.`);\n}","handlingStrategy":"validation","validationCode":"const roles = await fetchRoles(metadataUrl, apiKey);\nconst partnerRole =\n  roles.find((r) => r.label === PARTNER_ROLE_LABEL) ??\n  roles.find((r) => r.universalIdentifier === PARTNER_ROLE_UNIVERSAL_IDENTIFIER);\nif (!partnerRole) {\n  throw new Error(`Install/sync the partners app so the Partner role exists (uid=${PARTNER_ROLE_UNIVERSAL_IDENTIFIER})`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install and sync the partners app before rls:configure — the Partner role ships from the manifest.","Confirm the target workspace matches the app's universalIdentifier (PARTNER_ROLE_UNIVERSAL_IDENTIFIER must stay byte-identical).","Compare the printed 'Available roles' to PARTNER_ROLE_LABEL to catch renames.","Re-run rls:configure after the role appears (idempotent)."],"tags":["roles","rls","install","config","partners"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}