{"record":{"id":"291d937bd09a42a3","repo":"upstash/context7","slug":"proxy-error","errorCode":"proxy_error","errorMessage":"Failed to proxy authorization server metadata","messagePattern":"Failed to proxy authorization server metadata","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"packages/mcp/src/index.ts","lineNumber":584,"sourceCode":"                signal: abortSignal,\n              }),\n            async (response) => {\n              if (!response.ok) return { ok: false as const, status: response.status };\n              return { ok: true as const, metadata: await response.json() };\n            },\n            { abortSignal }\n          );\n          if (!upstream.ok) {\n            console.error(\"[OAuth] Upstream error:\", upstream.status);\n            return res.status(upstream.status).json({\n              error: \"upstream_error\",\n              message: \"Failed to fetch authorization server metadata\",\n            });\n          }\n          res.json(upstream.metadata);\n        } catch (error) {\n          console.error(\"[OAuth] Error fetching OAuth metadata:\", error);\n          res.status(502).json({\n            error: \"proxy_error\",\n            message: \"Failed to proxy authorization server metadata\",\n          });\n        }\n      }\n    );\n\n    // OpenAI Apps SDK domain verification challenge\n    app.get(\n      \"/.well-known/openai-apps-challenge\",\n      (_req: express.Request, res: express.Response) => {\n        if (!OPENAI_APPS_CHALLENGE_TOKEN) {\n          return res.status(404).json({\n            error: \"not_found\",\n            message: \"Endpoint not found.\",\n          });\n        }\n        res.type(\"text/plain\").send(OPENAI_APPS_CHALLENGE_TOKEN);","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/upstash/context7/blob/4416fb855b8f752be735e34f943b5d0762701aad/packages/mcp/src/index.ts#L566-L602","documentation":"The MCP server proxies /.well-known/oauth-authorization-server metadata from the upstream authorization server. If fetching that metadata throws (network error, bad URL, non-JSON response), the handler responds 502 with error code \"proxy_error\". The first variant (\"Failed to fetch authorization server metadata\") is sent when fetch succeeded but metadata is missing/invalid.","triggerScenarios":"GET the OAuth protected-resource/authorization-server metadata endpoint when the upstream auth server is unreachable, returns 5xx, or returns an unparseable body — the fetch/parse throws inside the route handler.","commonSituations":"Auth server temporarily down, misconfigured AUTH_ISSUER URL in server env, corporate network blocking the upstream host, or the issuer serving HTML instead of well-known JSON.","solutions":["Verify the authorization server URL configured in the MCP server env is correct and publicly reachable.","Curl the upstream /.well-known/oauth-authorization-server endpoint to confirm it returns valid JSON.","Retry after confirming the auth server is up (this is a 502 upstream outage).","Check DNS/firewall/proxy settings on the host running the MCP server."],"exampleFix":"// before\nAUTH_ISSUER=https://auth.internal.example  // unreachable from MCP host\n// after\nAUTH_ISSUER=https://auth.example.com       // publicly reachable, serves valid metadata","handlingStrategy":"retry","validationCode":"const url = `${issuer.replace(/\\/$/, '')}/.well-known/oauth-authorization-server`;\nconst ok = await fetch(url).then(r => r.ok).catch(() => false);\nif (!ok) throw new Error(`Auth server metadata unreachable: ${url}`);","typeGuard":"function isProxyError(res: unknown): res is { error: 'proxy_error'; message: string } {\n  return typeof res === 'object' && res !== null &&\n    (res as any).error === 'proxy_error';\n}","tryCatchPattern":"try {\n  metadata = await fetchAuthMetadata(issuer);\n} catch (e) {\n  if (isProxyError(e?.body)) {\n    await sleep(backoff(attempt++));\n    metadata = await fetchAuthMetadata(issuer); // upstream outage, retry\n  } else throw e;\n}","preventionTips":["Verify the AUTH_ISSUER URL is reachable from the MCP host before startup","Add a readiness check that curls the well-known metadata endpoint","Use a health-checked, HA auth server endpoint","Alert on 502 proxy_error responses to catch auth-server outages early"],"tags":["oauth","proxy","upstream"],"backgroundTag":"upstream-api-error","analyzedSha":"4416fb855b8f752be735e34f943b5d0762701aad","analyzedAt":"2026-09-16T20:28:07.148Z","contentChangedAt":"2026-09-16T20:28:07.148Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}