Files
orca/src/main/github/gh-error-classification.ts
T
0ec3882cb8 Add project Windows runtime selection (#5519)
* Add project Windows runtime selection

* Fix project Windows runtime selection

Co-authored-by: Orca <help@stably.ai>

* fix: preserve WSL shell variables

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Neil <neil@stably.ai>
2026-06-17 16:08:14 -07:00

56 lines
2.3 KiB
TypeScript

import type { ClassifiedError } from '../../shared/types'
// Why: gh CLI surfaces API errors as unstructured stderr. Map known
// patterns to typed errors so callers can show user-friendly messages.
export function classifyGhError(stderr: string): ClassifiedError {
const s = stderr.toLowerCase()
if (s.includes('http 403') || s.includes('resource not accessible')) {
return {
type: 'permission_denied',
message: "You don't have permission to edit this issue. Check your GitHub token scopes."
}
}
if (s.includes('http 404') || s.includes('could not resolve to a repository')) {
return { type: 'not_found', message: 'Issue not found — it may have been deleted.' }
}
if (s.includes('has disabled issues')) {
return { type: 'issues_disabled', message: 'Issues are disabled on this repository.' }
}
if (s.includes('http 422') || s.includes('validation failed')) {
return { type: 'validation_error', message: `Invalid update — ${stderr.trim()}` }
}
if (s.includes('rate limit')) {
return {
type: 'rate_limited',
message: 'GitHub rate limit hit. Try again in a few minutes.'
}
}
if (
s.includes('timeout') ||
s.includes('no such host') ||
s.includes('network') ||
s.includes('could not resolve host')
) {
return { type: 'network_error', message: 'Network error — check your connection.' }
}
return { type: 'unknown', message: `Failed to update issue: ${stderr.trim()}` }
}
// Why: classifyGhError's copy is phrased for edit/update operations, but
// listIssues is a read op and renderer banners interpolate the message.
export function classifyListIssuesError(stderr: string): ClassifiedError {
const c = classifyGhError(stderr)
const trimmed = stderr.trim()
const readMessages: Record<ClassifiedError['type'], string> = {
permission_denied:
"You don't have permission to read issues for this repository. Check your GitHub token scopes.",
not_found: 'Repository not found.',
issues_disabled: 'Issues are disabled on this repository.',
validation_error: `Invalid request — ${trimmed}`,
rate_limited: 'GitHub rate limit hit. Try again in a few minutes.',
network_error: 'Network error — check your connection.',
unknown: `Failed to load issues: ${trimmed}`
}
return { type: c.type, message: readMessages[c.type] }
}