{"record":{"id":"6ef488c90e9cd371","repo":"Hmbown/CodeWhale","slug":"enter-a-runtime-token-to-connect-once","errorCode":null,"errorMessage":"Enter a Runtime token to connect once","messagePattern":"Enter a Runtime token to connect once","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_mobile.html","lineNumber":375,"sourceCode":"        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      }\n      if (!res.ok) {\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      }","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_mobile.html#L357-L393","documentation":"connectMobileSession requires a Runtime bearer token to authenticate the one-time POST to /__codewhale/mobile/session. The token() accessor returning an empty value means the user has not entered a token, so the runtime throws before making any network request.","triggerScenarios":"Tapping connect without typing a Runtime token into the token input; the token field was cleared or never populated on page load.","commonSituations":"First-time setup where the user skips the token field; token lost after localStorage/session clear; UI event firing before the user finished entering the token.","solutions":["Enter a Runtime token in the mobile UI's token field before connecting.","Ensure the token input's value is wired to the token() accessor correctly.","If the token should be pre-provisioned, populate it into the field/storage before calling connectMobileSession."],"exampleFix":"// before\nawait connectMobileSession();\n// after\nif (!tokenInput.value.trim()) { showHint('Enter a Runtime token first'); return; }\nawait connectMobileSession();","handlingStrategy":"validation","validationCode":"const runtimeToken = tokenInput.value.trim();\nif (!runtimeToken) { showHint('Enter a Runtime token first'); return; }","typeGuard":"function hasToken(t) { return typeof t === 'string' && t.trim().length > 0; }","tryCatchPattern":"try {\n  await connectMobileSession();\n} catch (e) {\n  if (String(e.message).includes('token')) focusTokenInput();\n}","preventionTips":["Disable the connect button until the token field is non-empty.","Persist a validated token so it survives reloads.","Focus the token input automatically when it is empty on connect."],"tags":["authentication","token","mobile"],"backgroundTag":"authentication-required","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}