mastra-ai/mastra · error · AuthFailureError
AuthFailureError(authFailureStatus, error)
Error message
AuthFailureError(authFailureStatus, error)
What it means
AuthFailureError is thrown by fetchWithAuthFailureHandling when the exporter's HTTP request (via fetchWithRetry inside batchUpload) received a 401 or 403 response. On the first auth-failing response, retries are suppressed (shouldRetryResponse returns false) and the original error is wrapped as AuthFailureError carrying the HTTP status and the underlying error as `cause`. This signals the exporter's credentials are invalid or insufficient, triggering the AuthFailureCooldown backoff instead of pointless retries.
Source
Thrown at observability/mastra/src/exporters/auth-failure-cooldown.ts:49
maxRetries: number,
callerShouldRetry?: (response: Response) => boolean,
): Promise<Response> {
let authFailureStatus: number | undefined;
try {
return await fetchWithRetry(url, options, maxRetries, {
shouldRetryResponse: response => {
if (isAuthFailureStatus(response.status)) {
authFailureStatus = response.status;
return false;
}
return callerShouldRetry?.(response) ?? true;
},
});
} catch (error) {
if (authFailureStatus !== undefined) {
throw new AuthFailureError(authFailureStatus, error);
}
throw error;
}
}
export class AuthFailureCooldown {
private failureCount = 0;
private cooldownUntilMs = 0;
private droppedEventsDuringCooldown = 0;
constructor(
private readonly exporterName: string,
private readonly getLogger: () => IMastraLogger,
) {}
private shouldDropEvents(): boolean {
return Date.now() < this.cooldownUntilMs;View on GitHub (pinned to 75dd419e61)
Solutions
- Check the `status` property (401 vs 403) and the `cause` to determine whether the key is unrecognized (401) or lacks permission (403).
- Regenerate or rotate the exporter's API key/token and update the environment variable or exporter config, then restart the process.
- Verify the Authorization header/credentials are actually attached to the exporter request and are scoped to the correct project/region.
- Wait out the AuthFailureCooldown backoff (60s doubling to a 15-minute cap) after fixing credentials — note any events dropped during cooldown in the reset() return value.
- Test the key with a direct curl to the export endpoint to confirm auth works before re-enabling exports.
Example fix
// before
new Exporter({ apiKey: process.env.STALE_OBSERVABILITY_KEY })
// after
new Exporter({ apiKey: process.env.NEW_OBSERVABILITY_KEY }) // rotated key, verified with curl -H "Authorization: Bearer $NEW_OBSERVABILITY_KEY" Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify credentials before enabling the exporter
const res = await fetch(exportEndpoint, { headers: { Authorization: `Bearer ${apiKey}` }, method: 'HEAD' });
if (res.status === 401 || res.status === 403) {
throw new Error(`Observability credentials rejected with ${res.status}; rotate the key before starting exports.`);
} Type guard
function isAuthFailureError(e: unknown): e is AuthFailureError {
return e instanceof AuthFailureError;
} Try / catch
import { isAuthFailureError } from '@mastra/observability/exporters/auth-failure-cooldown';
try {
await exporter.batchUpload(signals);
} catch (err) {
if (isAuthFailureError(err)) {
logger.error(`Exporter auth failed (HTTP ${err.status}). Rotate credentials; cooldown active.`, { cause: err.cause });
// do not retry immediately — AuthFailureCooldown backs off 60s -> 15min
} else {
throw err;
}
} Prevention
- Monitor key expiry and rotate observability API keys on a schedule before they lapse.
- Add a startup preflight that hits the export endpoint to verify credentials early.
- Ensure the Authorization header/credential env var is actually injected in the deploy environment.
- Use 401 vs 403 from err.status to distinguish bad-key vs insufficient-permissions when triaging.
- After fixing credentials, call reset() on AuthFailureCooldown and log how many events were dropped during cooldown.
When it happens
Trigger: batchUpload (traces/logs export) hitting the observability backend which responds 401 Unauthorized or 403 Forbidden: expired/rotated API keys, missing Authorization header, revoked service-account tokens, or insufficient permissions for the endpoint.
Common situations: Expired API key in the observability provider dashboard; credentials rotated in the environment but the process still runs with old values; a token scoped to a different project/region; clock drift invalidating short-lived JWTs; exporting to an endpoint the API key has no access to.
Related errors
- Failed to list projects (${res.status})
- Failed to create access token (${res.status})
- Slack OAuth HTTP error: ${tokenResponse.status} ${tokenRespo
- Failed to stream background tasks: ${response.statusText}
- Failed to stream agent builder action: ${response.statusText
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/2a15879a64b8eb16.
Report an issue: GitHub.