{"record":{"id":"5133e3a071a10b51","repo":"stablyai/orca","slug":"bitbucket-request-failed-http-response-status","errorCode":null,"errorMessage":"Bitbucket request failed: HTTP ${response.status}","messagePattern":"Bitbucket request failed: HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/bitbucket/client.ts","lineNumber":102,"sourceCode":"      throw new Error('Bitbucket request failed: no usable credential')\n    }\n    return null\n  }\n  try {\n    const response = await fetch(apiUrl(config.baseUrl, path, options.searchParams), {\n      headers: {\n        Accept: 'application/json',\n        ...authHeaders(config)\n      },\n      signal: AbortSignal.timeout(options.timeoutMs ?? REQUEST_TIMEOUT_MS)\n    })\n    if (!response.ok) {\n      await cancelUnreadResponseBody(response)\n      if (response.status === 404 && notFoundIsNull) {\n        return null\n      }\n      if (throwOnFailure) {\n        throw new Error(`Bitbucket 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\nfunction encodedRepoPath(repo: BitbucketRepoRef): string {\n  return `${encodeURIComponent(repo.workspace)}/${encodeURIComponent(repo.repoSlug)}`\n}\n\nfunction escapeBitbucketQueryString(value: string): string {\n  return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/bitbucket/client.ts#L84-L120","documentation":"Thrown by the Bitbucket requestJson helper when the HTTP response is not ok (and not a 404-with-notFoundIsNull case) and the caller passed throwOnFailure=true. The status code is interpolated into the message. It represents a definitive transport/auth/server failure that the caller explicitly asked to surface rather than collapse to null.","triggerScenarios":"A Bitbucket API call with throwOnFailure=true returning 401/403 (bad/expired app password), 429 (rate limited), 500 (server error), or a non-404 4xx (bad query/path). Timeouts and network errors are re-thrown by the outer catch as well.","commonSituations":"Expired or revoked app password, insufficient repository permission, wrong workspace/repo slug, Bitbucket rate limiting, or a network interruption.","solutions":["Map response.status: 401/403 -> refresh the app password; 404 (when not notFoundIsNull) -> verify workspace/repo slug; 429 -> back off; 5xx -> retry.","Catch the Error in the throwOnFailure caller and present it as a review-lookup transport failure.","Verify the BitbucketRepoRef (workspace, repoSlug) before calling.","Confirm the app password has the required scopes (Repositories: Read, Pull requests: Read)."],"exampleFix":"// before\nconst pr = await requestJson(path, {}, true)\n\n// after\nlet pr\ntry {\n  pr = await requestJson(path, {}, true)\n} catch (err) {\n  if (/HTTP 401|HTTP 403/.test(err.message)) {\n    throw new Error('Bitbucket credential rejected — refresh your app password')\n  }\n  throw err\n}","handlingStrategy":"try-catch","validationCode":"import { resolveBitbucketAuthConfig, hasAuth } from './bitbucket-auth-config'\\n\\nif (!hasAuth(resolveBitbucketAuthConfig())) {\\n  throw new Error('Bitbucket credential required')\\n}\\n// verify workspace/repo slug shape before the call","typeGuard":null,"tryCatchPattern":"try {\\n  return await requestJson(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('Bitbucket credential rejected — refresh your app password')\\n  }\\n  if (/HTTP 429/.test(msg)) {\\n    await backoff()\\n    return await requestJson(path, options, true)\\n  }\\n  throw err\\n}","preventionTips":["Verify the BitbucketRepoRef (workspace, repoSlug) before calling.","Confirm the app password has Repositories: Read and Pull requests: Read scopes.","Map HTTP status codes to remediation guidance.","Back off on 429 rate-limit responses."],"tags":["bitbucket","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"}