stablyai/orca · error
GitLab returned an error: ${reported}
Error message
GitLab returned an error: ${reported} What it means
Thrown by parseGlabJsonList when glab returned a JSON object (not an array) that carries a GitLab error envelope — specifically an object with a string `message` or `error` field. glab exits 0 on many error envelopes (and on proxy interstitials), so without this guard `JSON.parse(...).map` would throw an opaque `.map is not a function`. The reported text is truncated to REPORTED_PAYLOAD_LIMIT (300 chars).
Source
Thrown at src/main/gitlab/glab-api-response.ts:47
export class GlabNonListResponseError extends Error {}
// Why: glab allows a 10MB body; this is what keeps a proxy's whole response out of the error banner.
const REPORTED_PAYLOAD_LIMIT = 300
/**
* Parse a glab list response, failing readably when GitLab answers with a JSON object.
*
* Why: glab exits 0 on error envelopes and proxy wrappers, so `JSON.parse(...).map` threw an
* opaque `.map is not a function` that the caller's classifier could only report as "unknown".
*/
export function parseGlabJsonList<T>(payload: string): T[] {
const parsed: unknown = JSON.parse(payload)
if (Array.isArray(parsed)) {
return parsed as T[]
}
const reported = gitlabErrorText(parsed)
if (reported) {
throw new Error(`GitLab returned an error: ${reported}`)
}
// Why: slice the raw payload rather than re-serializing `parsed` — same text, without
// stringifying a multi-megabyte body just to keep the preview.
throw new GlabNonListResponseError(
`GitLab returned a non-list response: ${payload.trim().slice(0, REPORTED_PAYLOAD_LIMIT)}`
)
}
/** GitLab reports API failures as `{ message }` or `{ error }`; anything else is opaque data. */
function gitlabErrorText(parsed: unknown): string | null {
if (typeof parsed !== 'object' || parsed === null) {
return null
}
const { message, error } = parsed as { message?: unknown; error?: unknown }
for (const value of [message, error]) {
if (typeof value === 'string' && value.trim()) {
return value.trim().slice(0, REPORTED_PAYLOAD_LIMIT)
}View on GitHub (pinned to 1136503c6a)
Solutions
- Read the reported text — it is the literal GitLab message and names the real cause (auth, scope, not-found, rate limit).
- Refresh the GitLab token / reconnect the integration if the message indicates 401/403.
- Verify the project path and endpoint path are correct for the target GitLab instance.
- If behind a proxy, confirm the proxy forwards the real GitLab response rather than its own error envelope.
Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeGitLabErrorEnvelope(payload: string): boolean {
try {
const v = JSON.parse(payload)
return !Array.isArray(v) && typeof v === 'object' && v !== null
&& (typeof (v as any).message === 'string' || typeof (v as any).error === 'string')
} catch { return false }
} Type guard
function isGitLabErrorEnvelope(parsed: unknown): parsed is { message?: string; error?: string } {
return typeof parsed === 'object' && parsed !== null
&& (typeof (parsed as any).message === 'string' || typeof (parsed as any).error === 'string')
} Try / catch
try {
const list = parseGlabJsonList<MrType>(payload)
// use list
} catch (error) {
if (error instanceof GlabNonListResponseError) { /* opaque, surface raw */ }
else if (error instanceof Error && error.message.startsWith('GitLab returned an error:')) {
// auth/scope/not-found — read message, refresh token or fix path
} else throw error
} Prevention
- Keep GitLab tokens fresh and scoped correctly for the operations you perform.
- Validate the endpoint path matches the GitLab instance's API version.
- Test glab commands against the target instance in isolation to distinguish provider errors from proxy errors.
When it happens
Trigger: Any glab list command (`glab api projects/:id/merge_requests`, `glab mr list`, etc.) where GitLab responds with `{ "message": "..." }` or `{ "error": "..." }` but glab still exits 0. Common with 401/403/404 envelopes, rate-limit notices, and reverse-proxy error pages that pass through as JSON.
Common situations: Expired or revoked GitLab token (401 envelope); insufficient scope (403); project path/MR iid mismatch (404); GitLab self-hosted behind a proxy that returns its own JSON error; rate limiting (`{ message: "429 Too Many Requests" }`).
Related errors
- GitLab returned a non-list response: ${payload.trim().slice(
- GitHub request failed ${res.status} ${res.statusText}: ${bod
- token is required
- envelope.error.message
- token is required
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/bfd03854ddcad548.
Report an issue: GitHub.