cube-js/cube · error · Error
Access policy cannot have both 'group' and 'groups' properti
Error message
Access policy cannot have both 'group' and 'groups' properties.
Policy in cube '${cube.name}' has group '${groupDisplay}' and groups '${groupsDisplay}'.
Use either 'group' or 'groups', not both. What it means
Access policies accept either the singular 'group' or plural 'groups' property to declare which groups a policy applies to. A policy defining both is ambiguous, so getApplicablePolicies throws with the offending values and cube name.
Source
Thrown at packages/cubejs-server-core/src/core/CompilerApi.ts:433
protected hashRequestContext(context: Context): string {
if (!context.__hash) {
context.__hash = crypto.createHash('md5').update(JSON.stringify(context)).digest('hex');
}
return context.__hash;
}
protected async getApplicablePolicies(cube: EvaluatedCube, context: Context, compilers: Compiler): Promise<any[]> {
const cache = compilers.compilerCache.getRbacCacheInstance();
const cacheKey = `${cube.name}_${this.hashRequestContext(context)}`;
if (!cache.has(cacheKey)) {
const userGroups = await this.getGroupsFromContext(context);
const policies = cube.accessPolicy.filter((policy: AccessPolicyDefinition) => {
// Validate that policy doesn't have both group and groups
if (policy.group && policy.groups) {
const groupDisplay = Array.isArray(policy.group) ? policy.group.join(', ') : policy.group;
const groupsDisplay = Array.isArray(policy.groups) ? policy.groups.join(', ') : policy.groups;
throw new Error(
`Access policy cannot have both 'group' and 'groups' properties.\nPolicy in cube '${cube.name}' has group '${groupDisplay}' and groups '${groupsDisplay}'.\nUse either 'group' or 'groups', not both.`
);
}
const evaluatedConditions = (policy.conditions || []).map(
(condition: any) => compilers.cubeEvaluator.evaluateContextFunction(cube, condition.if, context)
);
// Check if policy matches by group or groups
let hasAccess = false;
if (policy.group) {
hasAccess = this.userHasGroup(userGroups, policy.group);
} else if (policy.groups) {
hasAccess = this.userHasGroup(userGroups, policy.groups);
} else {
// A policy without group/groups applies to everyone
hasAccess = this.userHasGroup(userGroups, '*');View on GitHub (pinned to 7d981676b3)
Solutions
- Remove the legacy 'group' key and keep only 'groups' (preferred plural array form)
- Or keep only 'group' if a single group is intended
- Search your schema for accessPolicy blocks containing both keys in the named cube
Example fix
// before
accessPolicy: [{ group: 'admin', groups: ['admin', 'analyst'] }]
// after
accessPolicy: [{ groups: ['admin', 'analyst'] }] Defensive patterns
Strategy: validation
Validate before calling
function validatePolicy(p) {
if (p.group && p.groups) throw new Error(`accessPolicy has both 'group' and 'groups': ${JSON.stringify(p)}`);
} Type guard
const isPolicyGroups = (p: AccessPolicyDefinition): p is AccessPolicyDefinition & { group?: never } => !('group' in p) || !('groups' in p); Try / catch
try { const policies = getApplicablePolicies(cubes, context, compilers); } catch (e) { if (/both 'group' and 'groups'/.test(e.message)) { /* flag offending cube */ } else throw e; } Prevention
- Standardize on 'groups' in all schemas
- Add a schema lint to reject both keys
- Audit generated schemas for legacy 'group'
- Document the migration path from group to groups
When it happens
Trigger: A cube's accessPolicy entry includes both keys, typically after migrating config from the old singular form to the plural array form without removing 'group'.
Common situations: Copy-pasted policy definitions, incremental migration where one policy still has the legacy 'group' alongside new 'groups', or code-generated schemas emitting both keys.
Related errors
- Access policy condition must return boolean, got ${JSON.stri
- maskedMembers cannot be provided in the query
- A user-defined contextToApiScopes function returns an incons
- A user-defined contextToApiScopes function returns a wrong s
- You cannot change security context via __user from ${session
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/489fdf045ec28559.
Report an issue: GitHub.