mastra-ai/mastra · error

Google RBAC roleMapping is required.

Error message

Google RBAC roleMapping is required.

What it means

Thrown synchronously in the MastraRBACGoogle constructor when the options object has no roleMapping. The provider maps Google Workspace group emails to Mastra roles/permissions via this mapping, so it is mandatory; without it the RBAC provider cannot resolve permissions.

Source

Thrown at auth/google/src/rbac-provider.ts:41

interface GroupsListResponse {
  groups?: GoogleWorkspaceGroup[];
  nextPageToken?: string;
}

export class MastraRBACGoogle implements IRBACProvider<GoogleUser> {
  private options: MastraRBACGoogleOptions;
  private rolesCache: LRUCache<string, Promise<string[]>>;
  private accessToken?: string;
  private tokenExpiresAt = 0;
  private tokenRefreshPromise?: Promise<string>;

  get roleMapping(): RoleMapping {
    return this.options.roleMapping;
  }

  constructor(options: MastraRBACGoogleOptions) {
    if (!options.roleMapping) {
      throw new Error('Google RBAC roleMapping is required.');
    }

    this.options = options;
    this.accessToken = options.accessToken;
    this.rolesCache = new LRUCache<string, Promise<string[]>>({
      max: options.cache?.maxSize ?? DEFAULT_CACHE_MAX_SIZE,
      ttl: options.cache?.ttlMs ?? DEFAULT_CACHE_TTL_MS,
    });
  }

  async getRoles(user: GoogleUser): Promise<string[]> {
    if (Array.isArray(user.groups)) {
      return user.groups;
    }

    const userKey = this.resolveUserKey(user);
    if (!userKey) {
      return [];

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass a roleMapping object (group email -> roles/permissions, plus optional '_default') in MastraRBACGoogle options.
  2. If options come from env/config, validate the mapping is present and non-empty before constructing the provider.
  3. Check for key spelling mismatches (roleMapping vs roleMappings) in your config loader.
  4. Fall back to a sensible default mapping if you intend a no-op provider (e.g. { _default: [] }).

Example fix

// before
const rbac = new MastraRBACGoogle({ accessToken: token });
// after
const rbac = new MastraRBACGoogle({
  accessToken: token,
  roleMapping: {
    'eng@mycompany.com': ['admin'],
    '_default': ['viewer'],
  },
});
Defensive patterns

Strategy: validation

Validate before calling

function assertRoleMapping(opts: { roleMapping?: Record<string, unknown> }): void {
  if (!opts.roleMapping || typeof opts.roleMapping !== 'object' || Object.keys(opts.roleMapping).length === 0) {
    throw new Error('MastraRBACGoogle requires a non-empty roleMapping');
  }
}
// call before: new MastraRBACGoogle(options)

Type guard

function hasRoleMapping(o: unknown): o is { roleMapping: Record<string, unknown> } {
  return typeof o === 'object' && o !== null && 'roleMapping' in o && typeof (o as any).roleMapping === 'object' && (o as any).roleMapping !== null;
}

Try / catch

let rbac: MastraRBACGoogle;
try {
  rbac = new MastraRBACGoogle(options);
} catch (err) {
  if (err instanceof Error && err.message === 'Google RBAC roleMapping is required.') {
    throw new Error('Startup config error: provide roleMapping in MastraRBACGoogle options');
  }
  throw err;
}

Prevention

When it happens

Trigger: new MastraRBACGoogle({...}) called with options.roleMapping undefined or null — e.g. omitted entirely, loaded from env/config that failed to parse, or passing an empty variable.

Common situations: Config typo (roleMappings vs roleMapping); wiring RBAC options from an untyped JSON/env source where the key is missing; building options conditionally and skipping the mapping; upgrading and not noticing roleMapping became required.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/6141cbccdbc46ba7. Report an issue: GitHub.