twentyhq/twenty · error · Error
upsertRowLevelPermissionPredicates returned no predicate for
Error message
upsertRowLevelPermissionPredicates returned no predicate for workspaceMember
What it means
Thrown by the partner RLS script after upserting a single workspaceMember predicate (`id IS the current member`) that scopes the partner role's read to its own member record. The code indexes `predicates[0]` from the mutation result; if the array is empty the predicate was not persisted, so the role would have no scoping rule and the script aborts. Like error 20, this is a provisioning-script hard stop, not user-facing runtime.
Source
Thrown at packages/twenty-apps/internal/twenty-partners/src/scripts/configure-partner-rls.ts:575
input: {
roleId: partnerRole.id,
objectMetadataId: workspaceMemberId,
predicates: [
{
fieldMetadataId: workspaceMemberIdFieldId,
operand: 'IS',
workspaceMemberFieldMetadataId: workspaceMemberIdFieldId,
},
],
predicateGroups: [],
} satisfies UpsertPredicatesInput,
});
const wmPredicate =
wmData.upsertRowLevelPermissionPredicates.predicates[0];
if (!wmPredicate) {
throw new Error(
'upsertRowLevelPermissionPredicates returned no predicate for workspaceMember',
);
}
results.push(wmPredicate);
console.log(
`[rls:configure] ✓ workspaceMember: predicate id=${wmPredicate.id} ` +
`(fieldMetadataId=${wmPredicate.fieldMetadataId}, operand=${wmPredicate.operand})`,
);
}
console.log(
`\n[rls:configure] Done — ${results.length} predicates upserted on Partner role ` +
`(${SIMPLE_TARGET_OBJECTS.length} simple objects + opportunity OR group + workspaceMember self-scope)`,
);
console.log(`\n${APPLY_WORKFLOW_WARNING}`);
// ── 5. Verify Opportunity field permissions (set via manifest, not here — see header) ─View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Log `wmData.upsertRowLevelPermissionPredicates` in full before the index access to confirm whether `predicates` is empty versus the whole response being malformed.
- Verify `workspaceMemberIdFieldId` and `workspaceMemberId` (object metadata id) resolve to the workspaceMember object/field in this workspace via a `fieldMetadata`/`objectMetadata` query.
- Confirm `partnerRole.id` is still valid and that RLS is enabled on the workspaceMember object.
- Re-run against a freshly reset workspace so the metadata IDs the script depends on are present.
Example fix
// before
const wmPredicate = wmData.upsertRowLevelPermissionPredicates.predicates[0];
if (!wmPredicate) {
throw new Error('upsertRowLevelPermissionPredicates returned no predicate for workspaceMember');
}
// after — guard the whole response shape, not just index 0
const wmPredicates = wmData?.upsertRowLevelPermissionPredicates?.predicates;
if (!Array.isArray(wmPredicates) || wmPredicates.length === 0) {
throw new Error(
`upsertRowLevelPermissionPredicates returned no predicate for workspaceMember (roleId=${partnerRole.id}, fieldMetadataId=${workspaceMemberIdFieldId})`,
);
} Defensive patterns
Strategy: validation
Validate before calling
// Before the workspaceMember upsert, confirm the field + object exist.
const wmField = await fetchFieldMetadataById(metadataUrl, apiKey, workspaceMemberIdFieldId);
if (!wmField) {
throw new Error(`workspaceMember field ${workspaceMemberIdFieldId} not found in workspace`);
} Type guard
const hasPredicate = (
data: unknown,
): data is { upsertRowLevelPermissionPredicates: { predicates: [{ id: string }] } } =>
typeof data === 'object' &&
data !== null &&
Array.isArray((data as any).upsertRowLevelPermissionPredicates?.predicates) &&
(data as any).upsertRowLevelPermissionPredicates.predicates.length > 0; Prevention
- Resolve workspaceMember object/field IDs from universal identifiers each run instead of trusting constants.
- Validate the partnerRole.id is still present before the upsert loop.
- Treat an empty predicates array as a hard configuration error and log the full mutation response.
- Run against a clean, freshly seeded workspace.
When it happens
Trigger: Calling `upsertRowLevelPermissionPredicates` for the workspaceMember object with a `workspaceMemberIdFieldId` or `workspaceMemberId` (object metadata id) that does not exist in the target workspace, with RLS disabled on workspaceMember, or with a `partnerRole.id` that has already been deleted. An empty `predicates` array in the response triggers it.
Common situations: Running the configure script against a workspace that was reset or seeded with different universal identifiers, pointing at the wrong environment, or a stale `partnerRole` lookup earlier in the script that returned a role id the metadata layer rejects.
Related errors
- upsertRowLevelPermissionPredicates returned fewer than 2 pre
- Missing ${name} env var
- Missing ${name} env var
- createFileUpload mutation did not return an upload target
- on-opportunity-partner-assigned: ${failed} person clear(s) f
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/2c1f109658622c76.
Report an issue: GitHub.