{"record":{"id":"e5bc7cc25052b31e","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"upstream-request-failed","errorCode":null,"errorMessage":"Upstream request failed","messagePattern":"Upstream request failed","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"MemoryProxy/src/anthropicHandler.ts","lineNumber":509,"sourceCode":"        method: \"POST\",\n        headers: retryHeaders,\n        body: JSON.stringify(originalBody),\n        signal: AbortSignal.timeout(forwardTimeoutMs),\n      });\n      if (upstreamResp.ok) {\n        pipe.info(\"RETRY_SUCCESS\", `Retry returned ${upstreamResp.status}`);\n      } else {\n        pipe.error(\"RETRY_FAILED\", `Retry returned ${upstreamResp.status}`);\n      }\n      return { resp: upstreamResp, retried: true };\n    } catch (retryErr: unknown) {\n      if (isRateLimitExceededError(retryErr)) throw retryErr;\n      if (retryErr instanceof DOMException && retryErr.name === \"TimeoutError\") {\n        pipe.error(\"RETRY_FORWARD\", `Timeout after ${forwardTimeoutMs / 1000}s`);\n      } else {\n        pipe.error(\"RETRY_FORWARD\", retryErr);\n      }\n      throw new Error(\"Upstream request failed\");\n    }\n  }\n\n  if (forwardFailed && !shouldRetry) {\n    throw new Error(\"Upstream request failed\");\n  }\n\n  if (!upstreamResp) {\n    throw new Error(\"No upstream response available\");\n  }\n\n  return { resp: upstreamResp, retried: false };\n}\n\n/** Main handler for POST /v1/messages (Anthropic Messages API). */\nexport async function handleAnthropicMessages(\n  c: Context,\n  config: ProxyConfig,","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryProxy/src/anthropicHandler.ts#L491-L527","documentation":"forwardWithRetry in the Anthropic handler gives up forwarding the request to the upstream provider after exhausting the retry loop. When the final retry attempt itself fails (and it is not a rate-limit error that must propagate), it logs the underlying cause (timeout duration or the retry error) and throws a generic Error('Upstream request failed'), deliberately discarding the original error's identity from the caller.","triggerScenarios":"All forward attempts to the Anthropic upstream failed: network errors, connection refused, timeouts (TimeoutError after forwardTimeoutMs), 5xx responses consumed by retry logic, or fetch throwing mid-body on the last attempt — with the failure occurring inside the retry loop.","commonSituations":"Upstream provider outage or degraded region; forwardTimeoutMs too small for large requests; DNS/proxy misconfiguration in the runtime; rate-limit errors interleaved with other failures.","solutions":["Check the logs for the RETRY_FORWARD entry immediately preceding this error to see the real cause (timeout vs network error)","Increase forwardTimeoutMs if the last attempt was a timeout on large payloads","Verify upstream endpoint reachability from the proxy host (curl the upstream URL)","Inspect isRateLimitExceededError coverage — genuine 429s should propagate rather than be masked by this generic error"],"exampleFix":"// before\nthrow new Error(\"Upstream request failed\");\n// after\nconst cause = retryErr instanceof DOMException && retryErr.name === \"TimeoutError\"\n  ? `timeout after ${forwardTimeoutMs / 1000}s`\n  : String(retryErr);\nthrow new Error(`Upstream request failed: ${cause}`, { cause: retryErr });","handlingStrategy":"retry","validationCode":"const upstreamOk = await fetch(upstreamBaseUrl, { method: 'HEAD', signal: AbortSignal.timeout(3000) }).then(r => r.ok || r.status < 500).catch(() => false);\nif (!upstreamOk) throw new Error('upstream unreachable before forwarding');","typeGuard":"function isUpstreamFailure(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Upstream request failed';\n}","tryCatchPattern":"try {\n  return await forwardWithRetry(req, pipe);\n} catch (e) {\n  if (isUpstreamFailure(e)) {\n    // check pipe logs for RETRY_FORWARD cause; back off and requeue once\n    await sleep(1000);\n    return forwardWithRetry(req, pipe);\n  }\n  throw e;\n}","preventionTips":["Always read the RETRY_FORWARD log entry to learn the true cause","Size forwardTimeoutMs to your p99 upstream latency","Health-probe the upstream before forwarding large batches","Ensure rate-limit errors bypass this generic wrap and reach the caller"],"tags":["network","retry","upstream","proxy"],"backgroundTag":"upstream-request-failed","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}