{"record":{"id":"0e1630247821f97b","repo":"jackwener/OpenCLI","slug":"linux-do-requires-an-active-signed-in-browser-sess","errorCode":null,"errorMessage":"linux.do requires an active signed-in browser session","messagePattern":"linux\\.do requires an active signed-in browser session","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/linux-do/feed.js","lineNumber":103,"sourceCode":"      try { data = await res.json(); } catch {}\n      return {\n        ok: res.ok,\n        status: res.status,\n        data,\n        error: data === null ? 'Response is not valid JSON' : '',\n      };\n    } catch (error) {\n      return {\n        ok: false,\n        error: error instanceof Error ? error.message : String(error),\n      };\n    }\n  })()`);\n    if (!result) {\n        throw new CommandExecutionError('linux.do returned an empty browser response');\n    }\n    if (result.status === 401 || result.status === 403) {\n        throw new AuthRequiredError('linux.do', 'linux.do requires an active signed-in browser session');\n    }\n    if (!result.ok) {\n        throw new CommandExecutionError(result.error || `linux.do request failed: HTTP ${result.status ?? 'unknown'}`);\n    }\n    if (result.error) {\n        throw new CommandExecutionError(result.error, 'Please verify your linux.do session is still valid');\n    }\n    return result.data;\n}\nfunction findMatchingTag(records, value) {\n    const raw = value.trim();\n    const normalized = normalizeLookupValue(value);\n    return /^\\d+$/.test(raw)\n        ? records.find((item) => item.id === Number(raw)) ?? null\n        : records.find((item) => normalizeLookupValue(item.name) === normalized)\n            ?? records.find((item) => normalizeLookupValue(item.slug) === normalized)\n            ?? null;\n}","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linux-do/feed.js#L85-L121","documentation":"fetchLinuxDoJson drives the site through a local browser session; when the browser reports HTTP 401 or 403, the CLI throws AuthRequiredError because linux.do rejected the request as unauthenticated. This means the user's Discourse login cookie/session is missing, expired, or lacks permission for the endpoint. The library treats authentication as a prerequisite for any feed access, so it fails fast with an auth-specific error instead of a generic HTTP error.","triggerScenarios":"Calling any command backed by fetchLinuxDoJson (data, subData via `linux-do feed` with any --view/--tag/--category combination) when the browser fetch returns status 401 or 403: logged-out browser profile, expired linux.do session cookie, Cloudflare/Discourse blocking the automated browser, or accessing a restricted category/tag.","commonSituations":"User never signed into linux.do in the browser profile the CLI automates; session expired after weeks of inactivity; user logged out or rotated cookies; site tightened anti-bot measures; private category requires elevated trust level.","solutions":["Open linux.do in the automated browser and sign in so a fresh session cookie exists, then retry the command","Run `opencli linux-do tags` or a plain `opencli linux-do feed` to verify the session works before narrowing by tag/category","If the browser profile is wrong or headless, reconfigure the CLI to use a profile with a valid login","Check whether the target tag/category is private and requires a higher trust level on linux.do"],"exampleFix":"// before (shell)\nopencli linux-do feed --category 94   // AuthRequiredError: requires active signed-in browser session\n// after (shell)\n# sign in to linux.do in the browser the CLI drives, then:\nopencli linux-do feed --category 94","handlingStrategy":"try-catch","validationCode":"// Probe session health before fetching the feed\nimport { execCommand } from './browser-runner.js'; // the CLI's browser wrapper\nconst probe = await execCommand(`(async () => {\n    const r = await fetch('https://linux.do/session/current.json');\n    return { status: r.status };\n})()`);\nif (!probe || probe.status === 401 || probe.status === 403) {\n    throw new Error('Sign in to linux.do in the automated browser before running feed commands');\n}","typeGuard":"function hasAuthenticatedBrowserResult(result) {\n    return Boolean(result) && typeof result === 'object' &&\n        result.status !== 401 && result.status !== 403;\n}","tryCatchPattern":"import { AuthRequiredError } from '@jackwener/opencli/errors';\ntry {\n    const topics = await data();\n} catch (err) {\n    if (err instanceof AuthRequiredError) {\n        console.error('linux.do session missing/expired. Open the automated browser and sign in, then retry.');\n        process.exitCode = 2;\n    } else {\n        throw err;\n    }\n}","preventionTips":["Keep the automated browser profile persistently logged in to linux.do","Run a cheap session probe (e.g. /session/current.json) before long feed operations","Re-authenticate proactively when the session has been idle for weeks","Avoid logging out or clearing cookies in the browser profile the CLI uses"],"tags":["authentication","browser-session","http-401","http-403","cli"],"backgroundTag":"browser-session-auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}