{"record":{"id":"8b11c2da909b65bd","repo":"jackwener/OpenCLI","slug":"manus-api-auth-session-http-r-status","errorCode":null,"errorMessage":"Manus /api/auth/session HTTP ${r.status}","messagePattern":"Manus /api/auth/session HTTP (.+?)","errorType":"validation","errorClass":"AuthRequiredError","httpStatus":401,"severity":"error","filePath":"clis/manus/auth.js","lineNumber":35,"sourceCode":"      const r = await fetch('/api/auth/session', { credentials: 'include', headers: { Accept: 'application/json' } });\n      if (r.status === 401 || r.status === 403) {\n        return { kind: 'auth', detail: 'Manus /api/auth/session HTTP ' + r.status };\n      }\n      if (r.status === 503) {\n        return { kind: 'http', httpStatus: 503 };\n      }\n      if (!r.ok) return { kind: 'http', httpStatus: r.status };\n      const d = await r.json();\n      const u = d?.user || d;\n      if (!u || !(u.id || u.userId)) {\n        return { kind: 'auth', detail: 'Manus /api/auth/session 200 but no user' };\n      }\n      return { ok: true, user_id: String(u.id || u.userId), name: String(u.name || u.displayName || '') };\n    } catch (e) {\n      return { kind: 'exception', detail: String(e && e.message || e) };\n    }\n  })()`);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('manus.im', probe.detail);\n  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from Manus /api/auth/session`);\n  if (probe?.kind === 'exception') throw new CommandExecutionError(`Manus whoami failed: ${probe.detail}`);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected Manus probe: ${JSON.stringify(probe)}`);\n  return { user_id: probe.user_id, name: probe.name };\n}\n\nregisterSiteAuthCommands({\n  site: 'manus',\n  domain: 'manus.im',\n  loginUrl: 'https://manus.im/login',\n  columns: ['user_id', 'name'],\n  verify: verifyManusIdentity,\n  poll: async (page) => {\n    if (!await hasManusSessionCookie(page)) {\n      throw new AuthRequiredError('manus.im', 'Waiting for Manus session cookies');\n    }\n    return verifyManusIdentity(page);\n  },","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/manus/auth.js#L17-L53","documentation":"The in-page probe fetches /api/auth/session with credentials to verify the Manus identity. When the session cookie exists but the endpoint answers 401 or 403, the probe returns kind:'auth' and verifyManusIdentity throws AuthRequiredError with the status in the detail — meaning the stored credentials are present but rejected by the server.","triggerScenarios":"Running a manus auth/whoami flow when a stale, expired, or revoked auth_session/manus_token cookie is sent to /api/auth/session and the server responds 401/403; also when a 200 response contains no user object (line 28 returns the same 'auth' kind).","commonSituations":"Session expired server-side while cookie remains in the profile; Manus invalidated tokens after a security event or password change; account logged out from another device; API schema change leaves the session response without a user object; partially corrupted cookie value.","solutions":["Re-run opencli manus login to obtain fresh session cookies, replacing the rejected ones.","Clear manus.im cookies for the browser profile and log in again.","Confirm the account is still active and not logged out remotely (Manus web UI).","Check whether Manus changed the /api/auth/session response shape (no user object) and update the CLI if so.","If the CLI can't stay logged in, check for clock skew or proxies stripping/altering cookies."],"exampleFix":"// before: stale cookies auto-fail\nopencli manus whoami // AuthRequiredError: Manus /api/auth/session HTTP 401\n// after: refresh session programmatically\nawait page.goto('https://manus.im/login');\n// complete login, then retry\nopencli manus whoami","handlingStrategy":"try-catch","validationCode":"// pre-flight: check a session cookie exists AND is non-empty\nconst cookies = await page.getCookies({ url: 'https://manus.im' });\nconst s = cookies.find(c => c.name === 'auth_session');\nif (!s || !s.value) await manusLogin();","typeGuard":"function isAuthRejected(probe) { return probe?.kind === 'auth'; }","tryCatchPattern":"try {\n  const identity = await manusWhoami();\n} catch (e) {\n  if (e.name === 'AuthRequiredError' && /HTTP 40[13]/.test(e.message)) {\n    await clearManusCookies(); await manusLogin(); // stale token — re-auth\n  } else throw e;\n}","preventionTips":["Refresh session cookies proactively rather than waiting for server rejection.","Clear old manus.im cookies before re-login to avoid mixing stale tokens.","Watch for Manus API schema changes that remove the user object from session responses.","Handle both 401/403 and '200 but no user' as re-auth triggers."],"tags":["authentication","http-401","http-403","session-expired","manus"],"backgroundTag":"session-cookie-invalid","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}