{"record":{"id":"0235c740715ec310","repo":"Hmbown/CodeWhale","slug":"detail-http-res-status","errorCode":null,"errorMessage":"detail || (\"HTTP \" + res.status)","messagePattern":"detail \\|\\| \\(\"HTTP \" \\+ res\\.status\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_mobile.html","lineNumber":367,"sourceCode":"    function headers(extra = {}) {\n      const out = Object.assign({ \"Content-Type\": \"application/json\" }, extra);\n      if (state.requestProof) out[MOBILE_REQUEST_HEADER] = state.requestProof;\n      return out;\n    }\n\n    async function api(path, options = {}) {\n      const res = await fetch(path, Object.assign({}, options, {\n        credentials: \"same-origin\",\n        headers: headers(options.headers || {})\n      }));\n      if (!res.ok) {\n        if (res.status === 401) clearMobileSession();\n        let detail = await res.text();\n        try {\n          const parsed = JSON.parse(detail);\n          detail = parsed.error?.message || detail;\n        } catch (_) {}\n        throw new Error(detail || (\"HTTP \" + res.status));\n      }\n      if (res.status === 204) return null;\n      return res.json();\n    }\n\n    async function connectMobileSession() {\n      const runtimeToken = token();\n      if (!runtimeToken) throw new Error(\"Enter a Runtime token to connect once\");\n      let res;\n      try {\n        res = await fetch(\"/__codewhale/mobile/session\", {\n          method: \"POST\",\n          credentials: \"same-origin\",\n          headers: { \"Authorization\": \"Bearer \" + runtimeToken }\n        });\n      } finally {\n        $(\"token\").value = \"\";\n      }","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_mobile.html#L349-L385","documentation":"The generic api() helper in the mobile runtime throws an Error carrying the response's error message (extracted from JSON `error.message`) or, if the body is not parseable/useful, a plain \"HTTP <status>\" string for any non-ok response (with 401 additionally clearing the saved session).","triggerScenarios":"Any api() call where the server responds with a non-ok status: 401 (bad/expired proof), 404 (unknown thread/turn path), 5xx (Runtime error), or an empty body.","commonSituations":"Expired session proof giving 401; Runtime not running or restarting (connection failures/5xx); calling an endpoint path that does not exist on the deployed version.","solutions":["Read the thrown message: if it is \"HTTP 401\", reconnect the session with a fresh Runtime token.","If \"HTTP 404\" or 5xx, check the Runtime server is running the version matching the mobile page and that the requested thread/turn exists.","Retry after reconnecting; clear the session on 401 so the user re-authenticates."],"exampleFix":"// before\nconst data = await api('/v1/threads/' + id);\n// after\ntry {\n  const data = await api('/v1/threads/' + id);\n} catch (e) {\n  if (String(e.message) === 'HTTP 401') await connectMobileSession();\n  else showError(e.message);\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":null,"tryCatchPattern":"try {\n  const data = await api(url, opts);\n} catch (e) {\n  if (String(e.message) === 'HTTP 401') { clearMobileSession(); await connectMobileSession(); }\n  else displayError(e.message);\n}","preventionTips":["Handle 401 centrally by reconnecting the session.","Check Runtime reachability before issuing API calls.","Surface the parsed error.message to the user instead of the raw status."],"tags":["http","network","api"],"backgroundTag":"http-error-response","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}