mastra-ai/mastra · error · FGADeniedError
FGA denied for tool '${resourceId}'
Error message
FGA denied for tool '${resourceId}' What it means
When fine-grained authorization (FGA) is configured on the Mastra server, every tool execution is checked with the TOOLS_EXECUTE permission. If the request context cannot be resolved to an authenticated FGA user (resolveMappedFGAUser returns nothing), the server throws an FGADeniedError naming the tool resource — effectively denying tool execution for unidentified callers rather than executing tools as an implicit or anonymous user.
Source
Thrown at packages/mcp/src/server/server.ts:2858
}
}),
);
return accessible.filter((entry): entry is [string, (typeof this.convertedTools)[string]] => entry !== null);
}
private async enforceToolExecutionFGA(toolId: string, requestContext?: RequestContext): Promise<void> {
const fgaProvider = this.mastra?.getServer?.()?.fga;
if (!fgaProvider) {
return;
}
const { getMCPToolFGAResourceId, requireFGA, FGADeniedError, MastraFGAPermissions } =
await import('@mastra/core/auth/ee');
const resourceId = getMCPToolFGAResourceId(this.id, toolId);
const user = await this.resolveMappedFGAUser(requestContext);
if (!user) {
throw new FGADeniedError({ id: 'unknown' }, { type: 'tool', id: resourceId }, MastraFGAPermissions.TOOLS_EXECUTE);
}
const { resource, permission } = this.resolveToolFGAParams({
user,
resourceId,
requestContext,
permission: MastraFGAPermissions.TOOLS_EXECUTE,
});
await requireFGA({
fgaProvider,
user,
resource,
permission,
requestContext,
context: {
resourceId,
},
metadata: {View on GitHub (pinned to 75dd419e61)
Solutions
- Ensure the incoming request passes through Mastra auth middleware so an authenticated user is present in requestContext.
- Forward the requestContext (containing the resolved user) into executeTool calls.
- Verify the FGA user-mapping configuration in resolveMappedFGAUser matches how your auth provider issues identities.
- Temporarily disable FGA (no fga provider on the server) to confirm the error is auth-related, then fix the mapping.
- Grant the mapped user the TOOLS_EXECUTE permission (or your mapped permission) for the tool resource in your FGA policy.
Example fix
// before
await server.executeTool('getWeather', { location: 'London' });
// after
await server.executeTool('getWeather', { location: 'London' }, {
toolCallId: 'call_1',
requestContext: { 'user': req.user }
}); Defensive patterns
Strategy: validation
Validate before calling
const fgaEnabled = Boolean(mastra.getServer?.()?.fga);
const user = requestContext?.user;
if (fgaEnabled && !user) {
throw new Error('FGA is enabled: tool execution requires an authenticated user in requestContext');
} Type guard
function hasAuthenticatedUser(ctx?: { user?: unknown }): ctx is { user: { id: string } } {
return !!ctx && typeof ctx.user === 'object' && ctx.user !== null && typeof (ctx.user as any).id === 'string';
} Try / catch
try {
return await server.executeTool(toolId, args, { requestContext });
} catch (e) {
if (e?.name === 'FGADeniedError') {
throw new HttpError(403, `Not authorized to execute tool '${toolId}'`);
}
throw e;
} Prevention
- Route all tool-execution entry points through Mastra auth middleware so requestContext always carries the user.
- Forward requestContext into every programmatic executeTool call.
- Test FGA user mapping with a real token before deploying.
- Verify the mapped user holds TOOLS_EXECUTE (or your custom mapped permission) on the tool resource.
- Decide explicitly whether anonymous tool execution should be blocked; if FGA is on, it will be.
When it happens
Trigger: Calling executeTool (or listing tools through the FGA-filtered path) without supplying an authenticated user in requestContext while FGA is enabled on the Mastra server; a token/identity mapping configured in resolveMappedFGAUser that fails to resolve (expired/absent credentials); invoking server methods programmatically without forwarding the request context that carries the user identity.
Common situations: Requests that bypass the auth middleware (direct executeTool calls from custom routes) so no user lands in requestContext; misconfigured FGA user mapping so valid tokens don't resolve to users; testing locally with FGA enabled but no auth headers; service-to-service calls missing forwarded identity headers.
Related errors
- Session is not available to the current user
- No OAuth authorization is pending for this server. Call conn
- Bearer token required
- FGA authorization denied: authenticated user is required
- [mastra/auth-ee] FGA is configured but ${missingRoutes.lengt
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/1cfa924340e4b767.
Report an issue: GitHub.