stablyai/orca · error · Error

GitHub API ${method} ${path} failed with ${response.status}:

Error message

GitHub API ${method} ${path} failed with ${response.status}: ${formatApiError(data)}

What it means

Thrown by the api.request method when the GitHub API response is not ok (status outside 2xx). The message includes method, path, the HTTP status, and the API's error payload (data.message if present, else JSON.stringify(data)). This wraps any non-success GitHub REST response into a single error shape.

Source

Thrown at config/scripts/run-release-mac-build-workflow.mjs:170

  return {
    owner,
    repo,
    async request(method, path, body) {
      const response = await fetchImpl(`${options.apiBaseUrl}${path}`, {
        body: body == null ? undefined : JSON.stringify(body),
        headers: {
          Accept: 'application/vnd.github+json',
          Authorization: `Bearer ${options.token}`,
          'Content-Type': 'application/json',
          'X-GitHub-Api-Version': DEFAULT_API_VERSION
        },
        method
      })
      const text = await response.text()
      const data = text.length > 0 ? JSON.parse(text) : null

      if (!response.ok) {
        throw new Error(
          `GitHub API ${method} ${path} failed with ${response.status}: ${formatApiError(data)}`
        )
      }

      return data
    }
  }
}

function readWorkflowRunFromDispatchResult(result) {
  if (Number.isInteger(result?.workflow_run_id)) {
    return {
      html_url: result.html_url,
      id: result.workflow_run_id
    }
  }

  return null

View on GitHub (pinned to 1136503c6a)

Solutions

  1. For 401/403, verify GITHUB_TOKEN/GH_TOKEN is valid and has actions:write and contents:read scopes.
  2. For 404, confirm options.workflow file name and that the ref exists in the repo.
  3. For 403 rate limit, back off and retry; consider condensing calls.
  4. Read the data.message in the error to map the status to the GitHub reason.

Example fix

// before
await api.request('POST', `/repos/${owner}/${repo}/actions/workflows/${wf}/dispatches`, body)
// after
try {
  await api.request('POST', `/repos/${owner}/${repo}/actions/workflows/${encodeURIComponent(wf)}/dispatches`, body)
} catch (err) {
  // err.message: 'GitHub API POST .../dispatches failed with 404: Not Found'
  throw err
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canDispatch(api, options) {
  return Boolean(options.token && options.repo && options.workflow && options.ref)
}
if (!canDispatch(null, options)) {
  throw new Error('Missing token/repo/workflow/ref; cannot dispatch')
}

Type guard

function isApiErrorStatus(method, path, status) {
  return status === 401 || status === 403 || status === 404 || status === 422 || status >= 500
}

Try / catch

try {
  await api.request('POST', path, body)
} catch (err) {
  const m = err.message.match(/failed with (\d+):/)
  if (m) {
    const status = Number(m[1])
    if (status === 403 && /rate limit/i.test(err.message)) await sleep(backoffMs) // retry
    else if (status >= 500) await sleep(backoffMs) // retry once
    else throw err // 4xx is fatal
  } else throw err
}

Prevention

When it happens

Trigger: Any api.request(method, path, body) that yields response.ok === false: 401/403 auth or scopes, 404 wrong workflow/repo path, 422 malformed inputs, 409/500 server errors, or secondary rate limits (403 with a rate-limit message).

Common situations: Expired or under-scoped GITHUB_TOKEN, dispatching a workflow that does not exist (404 on .../dispatches), wrong ref (RELEASE_MAC_BUILD_REF), per-second rate limiting, dispatching to a repo the token cannot access.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/22bff7c6f82e4095. Report an issue: GitHub.