mastra-ai/mastra · error

Unsupported GitHub review state: ${state}

Error message

Unsupported GitHub review state: ${state}

What it means

parseReviewState maps GitHub's uppercase review state strings onto the library's Review['state'] union. Any state string outside the five known GitHub values (PENDING, COMMENTED, APPROVED, CHANGES_REQUESTED, DISMISSED) is rejected, meaning GitHub introduced a new state or the caller passed an already-lowercased/invalid value.

Source

Thrown at mastracode/factory/src/integrations/github/integration.ts:1459

function parseRequestedReviewers(data: {
  users?: Array<{ login?: string }> | null;
  teams?: Array<{ slug?: string }> | null;
  requested_reviewers?: Array<{ login?: string }> | null;
  requested_teams?: Array<{ slug?: string }> | null;
}) {
  return {
    users: (data.users ?? data.requested_reviewers ?? []).flatMap(user => (user.login ? [user.login] : [])),
    teams: (data.teams ?? data.requested_teams ?? []).flatMap(team => (team.slug ? [team.slug] : [])),
  };
}

function parseReviewState(state: string): Review['state'] {
  if (state === 'PENDING') return 'pending';
  if (state === 'COMMENTED') return 'commented';
  if (state === 'APPROVED') return 'approved';
  if (state === 'CHANGES_REQUESTED') return 'changes-requested';
  if (state === 'DISMISSED') return 'dismissed';
  throw new Error(`Unsupported GitHub review state: ${state}`);
}

function reviewEventToGithub(event: Exclude<InputOf<'createReview'>['event'], undefined>) {
  if (event === 'approve') return 'APPROVE' as const;
  if (event === 'request-changes') return 'REQUEST_CHANGES' as const;
  return 'COMMENT' as const;
}

function requirePullRequestNumber(value: string): number {
  return requirePositiveId(value, 'pull request');
}

function requirePositiveId(value: string, resource: string): number {
  const parsed = parsePositiveInteger(value);
  if (parsed === null) throw new Error(`GitHub ${resource} id must be a positive integer.`);
  return parsed;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass the raw uppercase state from the GitHub API, not a normalized value.
  2. Log the offending state value and check the GitHub REST API docs for new states.
  3. Add a mapping branch for any newly documented state.
  4. Map unknown states to a fallback like 'commented' only if your logic tolerates it — better to update the parser.

Example fix

// before
parseReviewState(review.state.toLowerCase());
// after
parseReviewState(review.state); // pass raw API value, e.g. 'CHANGES_REQUESTED'
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = ['PENDING','COMMENTED','APPROVED','CHANGES_REQUESTED','DISMISSED'] as const;
if (!(KNOWN as readonly string[]).includes(state)) throw new Error(`unknown review state: ${state}`);

Type guard

function isGithubReviewState(s: string): s is 'PENDING'|'COMMENTED'|'APPROVED'|'CHANGES_REQUESTED'|'DISMISSED' {
  return ['PENDING','COMMENTED','APPROVED','CHANGES_REQUESTED','DISMISSED'].includes(s);
}

Try / catch

try {
  return parseReviewState(rawState);
} catch (e) {
  log.warn('unknown review state', { rawState });
  return 'commented' as Review['state']; // or rethrow, per policy
}

Prevention

When it happens

Trigger: Fetching PR reviews while passing a custom state string; GitHub API returning an unexpected new state value; feeding lowercase 'approved' into parseReviewState instead of the raw API value.

Common situations: Caching review states and re-parsing stored (normalized) values; a GitHub API change adding a state; passing review.submitted state from a different API shape.

Related errors


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