{"record":{"id":"1633b2da0fe14d3c","repo":"twentyhq/twenty","slug":"upsertrowlevelpermissionpredicates-returned-no-pre","errorCode":null,"errorMessage":"upsertRowLevelPermissionPredicates returned no predicates for object \"${name}\"","messagePattern":"upsertRowLevelPermissionPredicates returned no predicates for object \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-apps/internal/twenty-partners/src/scripts/configure-partner-rls.ts","lineNumber":489,"sourceCode":"      input: {\n        roleId: partnerRole.id,\n        objectMetadataId: info.objectMetadataId,\n        predicates: [\n          {\n            fieldMetadataId: info.partnerUserFieldMetadataId,\n            operand: 'IS',\n            workspaceMemberFieldMetadataId: workspaceMemberIdFieldId,\n          },\n        ],\n        predicateGroups: [],\n      } satisfies UpsertPredicatesInput,\n    });\n\n    const predicate =\n      data.upsertRowLevelPermissionPredicates.predicates[0];\n\n    if (!predicate) {\n      throw new Error(\n        `upsertRowLevelPermissionPredicates returned no predicates for object \"${name}\"`,\n      );\n    }\n\n    results.push(predicate);\n    console.log(\n      `[rls:configure] ✓ ${name}: predicate id=${predicate.id} ` +\n        `(fieldMetadataId=${predicate.fieldMetadataId}, operand=${predicate.operand})`,\n    );\n  }\n\n  // Opportunity: (partnerUser IS me) OR (isListed = true) — listed briefs visible to all partners.\n  {\n    const oppPredicates = await upsertPredicates(\n      {\n        roleId: partnerRole.id,\n        objectMetadataId: opportunityObjectId,\n        predicateGroups: [","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-apps/internal/twenty-partners/src/scripts/configure-partner-rls.ts#L471-L507","documentation":"configure-partner-rls calls upsertRowLevelPermissionPredicates and expects at least one predicate back; it throws if the returned predicates array is empty. An empty result means the server accepted the upsert call but produced no predicate — a silent rejection (e.g. the field metadata id is invalid, the operand is unsupported, or a server-side guard dropped the predicate) that must not be treated as success.","triggerScenarios":"data.upsertRowLevelPermissionPredicates.predicates is empty/undefined after upserting for an object. Causes: the fieldMetadataId passed in is wrong/stale (the predicate can't bind); the operand 'IS' is unsupported for that field type; the role id is invalid; a server-side validation removed the predicate; metadata changed between the field lookup and the upsert.","commonSituations":"Metadata drift between findFieldByName and the upsert; wrong objectInfoByName entry passed; server version that changed the upsert return contract; field-locked field rejecting a predicate.","solutions":["Inspect the full upsert response (data.upsertRowLevelPermissionPredicates) for an errors/null payload — log it before the guard.","Confirm the fieldMetadataId and operand passed to the upsert are valid for the object/field type.","Re-sync metadata and re-run rls:configure (idempotent) so the field ids are current.","Reproduce the upsertRowLevelPermissionPredicates mutation in the GraphQL playground to read any server-side rejection."],"exampleFix":"// before\nconst predicate = data.upsertRowLevelPermissionPredicates.predicates[0];\nif (!predicate) {\n  throw new Error(`upsertRowLevelPermissionPredicates returned no predicates for object \"${name}\"`);\n}\n\n// after — surface the raw response and the field id used\nconst predicates = data.upsertRowLevelPermissionPredicates?.predicates ?? [];\nif (predicates.length === 0) {\n  throw new Error(\n    `upsertRowLevelPermissionPredicates returned no predicates for object \"${name}\" ` +\n    `(fieldMetadataId=${workspaceMemberIdFieldId}, operand=IS, response=${JSON.stringify(data)})`,\n  );\n}\nconst predicate = predicates[0];","handlingStrategy":"try-catch","validationCode":"// Validate field metadata ids are fresh before the upsert loop.\n// Re-sync metadata if any target object's partnerUser field id is stale.\nfor (const name of SIMPLE_TARGET_OBJECTS) {\n  const info = objectInfoByName.get(name);\n  if (!info?.partnerUserFieldMetadataId) {\n    throw new Error(`Missing partnerUser field metadata id for ${name}; re-sync metadata`);\n  }\n}","typeGuard":"const hasPredicate = (\n  r: unknown,\n): r is { upsertRowLevelPermissionPredicates: { predicates: [{ id: string }] } } =>\n  typeof r === 'object' && r !== null &&\n  Array.isArray((r as any).upsertRowLevelPermissionPredicates?.predicates) &&\n  (r as any).upsertRowLevelPermissionPredicates.predicates.length > 0;\n\nif (!hasPredicate(data)) {\n  throw new Error(`upsert returned no predicates for ${name}: ${JSON.stringify(data)}`);\n}","tryCatchPattern":"try {\n  await configureRls();\n} catch (err) {\n  // An empty predicates result is usually a stale field metadata id or a server-side guard.\n  // Re-sync metadata and re-run (idempotent); if it persists, reproduce the upsert in the playground.\n  console.error('rls:configure predicate upsert failed:', err instanceof Error ? err.message : err);\n  process.exit(1);\n}","preventionTips":["Re-sync metadata before running rls:configure so field metadata ids are current.","Inspect the full upsert response when predicates come back empty — log it before the guard.","Confirm the operand ('IS') is supported for the field type.","Reproduce upsertRowLevelPermissionPredicates in the GraphQL playground to read any server rejection."],"tags":["rls","metadata","config","partners"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}