{"record":{"id":"fe8dec806264065f","repo":"wavetermdev/waveterm","slug":"call-methodname-failed-resp-status-resp-s","errorCode":null,"errorMessage":"call ${methodName} failed: ${resp.status} ${resp.statusText}","messagePattern":"call (.+?) failed: (.+?) (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/app/store/wos.ts","lineNumber":128,"sourceCode":"        args: args,\n        uicontext: uiContext,\n    };\n    // usp is just for debugging (easier to filter URLs)\n    const methodName = `${service}.${method}`;\n    const usp = new URLSearchParams();\n    usp.set(\"service\", service);\n    usp.set(\"method\", method);\n    const webEndpoint = getWebServerEndpoint();\n    if (webEndpoint == null) throw new Error(`cannot call ${methodName}: no web endpoint`);\n    const url = webEndpoint + \"/wave/service?\" + usp.toString();\n    const fetchPromise = fetch(url, {\n        method: \"POST\",\n        body: JSON.stringify(waveCall),\n    });\n    const prtn = fetchPromise\n        .then((resp) => {\n            if (!resp.ok) {\n                throw new Error(`call ${methodName} failed: ${resp.status} ${resp.statusText}`);\n            }\n            return resp.json();\n        })\n        .then((respData: WebReturnType) => {\n            if (respData == null) {\n                return null;\n            }\n            if (respData.updates != null) {\n                updateWaveObjects(respData.updates);\n            }\n            if (respData.error != null) {\n                throw new Error(`call ${methodName} error: ${respData.error}`);\n            }\n            const durationStr = Date.now() - startTs + \"ms\";\n            debugLogBackendCall(methodName, durationStr, args);\n            return respData.data;\n        });\n    return prtn;","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/frontend/app/store/wos.ts#L110-L146","documentation":"callBackendService received an HTTP response whose resp.ok was false (status outside 200-299) and converts it into a thrown Error containing the status code and status text. This surfaces transport-level backend failures — auth rejection, server error, route not found — for any waveobj service call made through the generic service endpoint.","triggerScenarios":"POST to /wave/service returning 500 (backend exception), 401/403 (auth/token issues), 404 (endpoint/proxy misroute), 502/503 (server down or proxy cannot reach backend).","commonSituations":"Waveserver crashed or restarting while frontend keeps calling; session/auth token expiry returning 401; dev proxy pointing at the wrong backend port; backend panics on malformed request args.","solutions":["Read resp.status in the caught error: 401/403 → re-authenticate; 5xx → check waveserver logs; 404 → fix proxy/endpoint","Restart/verify the waveserver is running and reachable","Re-login or refresh the auth token if 401/403","Confirm the frontend's web server endpoint/port matches the actual backend","Add retry with backoff for transient 502/503 during server restarts"],"exampleFix":"// before\ntry {\n    await rpcService.Call(ctx, \"waveobj\", \"GetObject\", otype, oid);\n} catch (e) {\n    console.error(e);\n}\n// after\ntry {\n    await rpcService.Call(ctx, \"waveobj\", \"GetObject\", otype, oid);\n} catch (e) {\n    const m = String(e).match(/call .* failed: (\\d+)/);\n    if (m && (m[1] === \"502\" || m[1] === \"503\")) {\n        await retryWithBackoff(() => rpcService.Call(ctx, \"waveobj\", \"GetObject\", otype, oid));\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"retry","validationCode":"const resp = await fetch(webEndpoint + \"/wave/service?\" + usp);\nif (!resp.ok) {\n    console.error(\"backend service endpoint status:\", resp.status);\n}\n// then rely on callBackendService as usual","typeGuard":"function isTransportFailure(err: unknown): boolean {\n    return /call .* failed: \\d+/.test(String(err));\n}","tryCatchPattern":"try {\n    const result = await rpcService.Call(ctx, \"waveobj\", method, ...args);\n} catch (e) {\n    const m = String(e).match(/failed: (\\d+)/);\n    if (m && [\"502\", \"503\", \"504\"].includes(m[1])) {\n        return await retryWithBackoff(() => rpcService.Call(ctx, \"waveobj\", method, ...args));\n    }\n    if (m && (m[1] === \"401\" || m[1] === \"403\")) {\n        await reauthenticate();\n        return await rpcService.Call(ctx, \"waveobj\", method, ...args);\n    }\n    throw e;\n}","preventionTips":["Map status codes to actions: 401 → re-auth, 5xx → check server, 404 → fix proxy","Add retry with backoff for transient 5xx","Monitor waveserver health before issuing bursts of calls","Keep frontend/backend port and proxy config in sync"],"tags":["network","http","backend","wave"],"backgroundTag":"http-request-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}