{"record":{"id":"ba17812ce9345b57","repo":"stablyai/orca","slug":"azure-devops-request-failed-http-response-statu","errorCode":null,"errorMessage":"Azure DevOps request failed: HTTP ${response.status}","messagePattern":"Azure DevOps request failed: HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/azure-devops/azure-devops-api-request.ts","lineNumber":177,"sourceCode":"  const doFetch = (url: URL): Promise<Response> =>\n    fetch(url, {\n      headers: {\n        Accept: 'application/json',\n        ...authHeaders(config)\n      },\n      signal: AbortSignal.timeout(options.timeoutMs ?? REQUEST_TIMEOUT_MS)\n    })\n  try {\n    const url = apiUrl(baseUrl, path, options.searchParams)\n    let response = await doFetch(url)\n    if (await shouldRetryWithPreviewApiVersion(url, response)) {\n      markAzureDevOpsPreviewApiVersionOrigin(url.origin)\n      response = await doFetch(apiUrl(baseUrl, path, options.searchParams))\n    }\n    if (!response.ok) {\n      await cancelUnreadResponseBody(response)\n      if (throwOnFailure) {\n        throw new Error(`Azure DevOps request failed: HTTP ${response.status}`)\n      }\n      return null\n    }\n    return (await response.json()) as T\n  } catch (error) {\n    if (throwOnFailure) {\n      throw error\n    }\n    return null\n  }\n}\n\nexport function requestAzureDevOpsJson<T>(\n  repo: AzureDevOpsRepoRef,\n  path: string,\n  options: AzureDevOpsRequestOptions = {},\n  throwOnFailure = false\n): Promise<T | null> {","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/azure-devops/azure-devops-api-request.ts#L159-L195","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect response.status: 401/403 -> refresh/re-scope the PAT; 404 -> verify org/project/repo IDs; 5xx -> retry with backoff and check Azure status.","Catch the Error in the throwOnFailure caller and map it to a user-facing auth/transport message instead of treating it as 'no PR'.","Validate the AzureDevOpsRepoRef (org, project, repo) before issuing the request.","Confirm the PAT has the required scopes (e.g. Code: Read) for the endpoint."],"exampleFix":"// before\nconst pr = await requestAzureDevOpsJson(repo, path, {}, true)\n\n// after\nlet pr\ntry {\n  pr = await requestAzureDevOpsJson(repo, path, {}, true)\n} catch (err) {\n  throw new Error(`Azure DevOps lookup failed (check PAT and repo ref): ${err.message}`)\n}","handlingStrategy":"try-catch","validationCode":"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","typeGuard":null,"tryCatchPattern":"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}","preventionTips":["Validate the AzureDevOpsRepoRef (org, project, repo) before requesting.","Ensure the PAT has the required scopes and is not expired.","Map HTTP status codes to user-facing guidance.","Use throwOnFailure only where a null would cause a false 'no PR' result."],"tags":["azure-devops","network","http","auth","pull-request"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}