stablyai/orca · error · Error

Azure DevOps request failed: HTTP ${response.status}

Error message

Azure DevOps request failed: HTTP ${response.status}

What it means

Thrown by requestAzureDevOpsJsonAtBase when the HTTP response is not ok and the caller passed throwOnFailure=true. The function first retries once with a preview api-version on a VssInvalidPreviewVersionException 400, so this throw means the request genuinely failed (auth, permissions, server error, wrong path) even after that retry. Callers opt into throwOnFailure specifically to distinguish a real failure from an acceptable 'no PR' null.

Source

Thrown at src/main/azure-devops/azure-devops-api-request.ts:177

  const doFetch = (url: URL): Promise<Response> =>
    fetch(url, {
      headers: {
        Accept: 'application/json',
        ...authHeaders(config)
      },
      signal: AbortSignal.timeout(options.timeoutMs ?? REQUEST_TIMEOUT_MS)
    })
  try {
    const url = apiUrl(baseUrl, path, options.searchParams)
    let response = await doFetch(url)
    if (await shouldRetryWithPreviewApiVersion(url, response)) {
      markAzureDevOpsPreviewApiVersionOrigin(url.origin)
      response = await doFetch(apiUrl(baseUrl, path, options.searchParams))
    }
    if (!response.ok) {
      await cancelUnreadResponseBody(response)
      if (throwOnFailure) {
        throw new Error(`Azure DevOps request failed: HTTP ${response.status}`)
      }
      return null
    }
    return (await response.json()) as T
  } catch (error) {
    if (throwOnFailure) {
      throw error
    }
    return null
  }
}

export function requestAzureDevOpsJson<T>(
  repo: AzureDevOpsRepoRef,
  path: string,
  options: AzureDevOpsRequestOptions = {},
  throwOnFailure = false
): Promise<T | null> {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Inspect response.status: 401/403 -> refresh/re-scope the PAT; 404 -> verify org/project/repo IDs; 5xx -> retry with backoff and check Azure status.
  2. Catch the Error in the throwOnFailure caller and map it to a user-facing auth/transport message instead of treating it as 'no PR'.
  3. Validate the AzureDevOpsRepoRef (org, project, repo) before issuing the request.
  4. Confirm the PAT has the required scopes (e.g. Code: Read) for the endpoint.

Example fix

// before
const pr = await requestAzureDevOpsJson(repo, path, {}, true)

// after
let pr
try {
  pr = await requestAzureDevOpsJson(repo, path, {}, true)
} catch (err) {
  throw new Error(`Azure DevOps lookup failed (check PAT and repo ref): ${err.message}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { getAzureDevOpsAuthConfig } from './auth-config'\n\nconst config = getAzureDevOpsAuthConfig()\nif (!config?.token) {\n  throw new Error('Azure DevOps PAT is not configured')\n}\n// also verify repo ref shape before the request

Try / catch

try {\n  return await requestAzureDevOpsJson(repo, path, options, true)\n} catch (err) {\n  const msg = (err as Error).message\n  if (/HTTP 401|HTTP 403/.test(msg)) {\n    throw new Error('Azure DevOps auth failed — refresh your PAT')\n  }\n  if (/HTTP 404/.test(msg)) {\n    throw new Error('Azure DevOps resource not found — check org/project/repo')\n  }\n  throw err\n}

Prevention

When it happens

Trigger: Any Azure DevOps REST call with throwOnFailure=true that returns 401/403 (bad/expired PAT), 404 (wrong project/repo/ID), 500 (server error), or a non-preview 400 (malformed query). Also triggered by request timeouts or network errors that surface as non-ok.

Common situations: Expired or revoked Personal Access Token, wrong organization/project/repo in the repo ref, insufficient scope on the PAT, Azure DevOps service incident, or an incorrect API path.

Related errors


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