{"record":{"id":"f20e1f04a7e114f1","repo":"fatedier/frp","slug":"http-response-status","errorCode":null,"errorMessage":"HTTP ${response.status}","messagePattern":"HTTP \\$\\{response\\.status\\}","errorType":"http","errorClass":"HTTPError","httpStatus":null,"severity":"error","filePath":"web/frpc/src/api/http.ts","lineNumber":22,"sourceCode":"  status: number\n  statusText: string\n\n  constructor(status: number, statusText: string, message?: string) {\n    super(message || statusText)\n    this.status = status\n    this.statusText = statusText\n  }\n}\n\nasync function request<T>(url: string, options: RequestInit = {}): Promise<T> {\n  const defaultOptions: RequestInit = {\n    credentials: 'include',\n  }\n\n  const response = await fetch(url, { ...defaultOptions, ...options })\n\n  if (!response.ok) {\n    throw new HTTPError(\n      response.status,\n      response.statusText,\n      `HTTP ${response.status}`,\n    )\n  }\n\n  // Handle empty response (e.g. 204 No Content)\n  if (response.status === 204) {\n    return {} as T\n  }\n\n  const contentType = response.headers.get('content-type')\n  if (contentType && contentType.includes('application/json')) {\n    return response.json()\n  }\n  return response.text() as unknown as T\n}\n","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/web/frpc/src/api/http.ts#L4-L40","documentation":"Generic non-2xx failure from the frpc web dashboard's fetch wrapper. Every http.get/post/put/delete call in web/frpc/src/api goes through request(), and any response where response.ok is false throws an HTTPError whose message is just 'HTTP <status>'. The frpc admin API (admin_addr/admin_port) returns 4xx/5xx for bad payloads, unknown resources, or when the admin server is not enabled.","triggerScenarios":"Calling any frpc admin API endpoint (e.g. /api/proxy, /api/config, /api/status) while frpc's webServer/admin port returns a non-2xx status: 404 for an unknown route on the admin port, 401/403 when authentication is required, 500 when the config manager fails (e.g. invalid config body).","commonSituations":"Pointing the frpc dashboard at a port that is actually frps (or another service) so every route 404s; frpc started without webServer.serverPort so nothing is listening; an expired admin session; curl-level proxies returning 502 while developing the dashboard.","solutions":["Verify frpc is running with webServer (admin) enabled and the dashboard targets that exact host:port","Reproduce the failing call with curl against the admin API to see the raw status code","Inspect err.status in the catch block — the message alone only carries the number","For 401/403 check webServer.user/webServer.password credentials; for 404 check the endpoint path and frpc version"],"exampleFix":"// before\nconst proxies = await http.get('/api/proxy') // throws HTTP 404\n\n// after\ntry {\n  const proxies = await http.get('/api/proxy')\n} catch (e) {\n  if (e instanceof Error && 'status' in e) {\n    console.error('admin API failed with status', (e as any).status)\n  }\n  throw e\n}","handlingStrategy":"try-catch","validationCode":"// Verify the frpc admin API is reachable before issuing calls\nasync function assertAdminApiUp(base: string) {\n  const r = await fetch(`${base}/api/status`, { credentials: 'include' })\n  if (!r.ok) throw new Error(`frpc admin API not ready: HTTP ${r.status}`)\n}","typeGuard":"function isHTTPError(e: unknown): e is { status: number; statusText: string } & Error {\n  return e instanceof Error && typeof (e as any).status === 'number'\n}","tryCatchPattern":"try {\n  const data = await http.get<T>('/api/proxy')\n} catch (e) {\n  if (isHTTPError(e) && e.status === 404) return null\n  if (isHTTPError(e) && e.status === 401) { await relogin(); throw e }\n  throw e\n}","preventionTips":["Health-check the admin endpoint once at dashboard startup and surface a clear 'frpc unreachable' state","Centralize all API calls through the http wrapper so HTTPError status handling lives in one interceptor","Keep dashboard and frpc versions in lockstep so endpoint paths always match"],"tags":["http","typescript","frpc","admin-api","dashboard"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}