{"record":{"id":"58ff0b1fc924df5d","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-bilibili-unfollow","errorCode":null,"errorMessage":"Browser session required for bilibili unfollow","messagePattern":"Browser session required for bilibili unfollow","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/unfollow.js","lineNumber":53,"sourceCode":"cli({\n    site: 'bilibili',\n    name: 'unfollow',\n    access: 'write',\n    description: '取消关注 B站用户（官方 API，需登录）',\n    domain: 'www.bilibili.com',\n    strategy: Strategy.COOKIE,\n    args: [\n        {\n            name: 'target',\n            required: true,\n            positional: true,\n            help: '目标 UID / 用户名 / space.bilibili.com 链接',\n        },\n    ],\n    columns: ['mid', 'name', 'status', 'url'],\n    func: async (page, kwargs) => {\n        if (!page) {\n            throw new CommandExecutionError('Browser session required for bilibili unfollow');\n        }\n        const mid = await resolveTargetMid(page, kwargs.target);\n        const self = await getSelfUid(page);\n        if (mid === self) {\n            throw new ArgumentError('Cannot unfollow yourself');\n        }\n        const attribute = await fetchRelationAttribute(page, mid);\n        const url = `https://space.bilibili.com/${mid}`;\n        // attribute 2=following, 6=mutual. Anything else means the viewer isn't\n        // currently following — skip the POST and return idempotent status.\n        if (attribute !== 2 && attribute !== 6) {\n            return [{ mid, name: '', status: 'not-following', url }];\n        }\n        const payload = await apiPost(page, '/x/relation/modify', {\n            params: { fid: mid, act: 2, re_src: 11 },\n        });\n        requireOkPayload(payload, 'relation modify');\n        await waitForRelation(page, mid, (nextAttribute) => nextAttribute !== 2 && nextAttribute !== 6, 'not following');","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/unfollow.js#L35-L71","documentation":"The bilibili unfollow command's func requires an authenticated browser page; if `page` is null/undefined it throws CommandExecutionError 'Browser session required for bilibili unfollow'. Following/unfollowing is a write action tied to a logged-in session, so running headless without a browser session is unsupported.","triggerScenarios":"Invoking the bilibili unfollow command (CLI or its func) without an active browser session — e.g. running the CLI outside the interactive browser-backed environment, the session was closed, or the command runner passed no page object.","commonSituations":"Running the command in CI or a script without the browser daemon; the browser session expired or was closed between commands; forgetting to start the interactive session before issuing browser-dependent commands.","solutions":["Start/attach a browser session (log into bilibili) before running the unfollow command","Re-open the session if it was closed; confirm `page` is being passed to the command func","If scripting, use the session-aware runner rather than calling func(page=null) directly"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if (typeof page === 'undefined' || page === null) {\n  throw new Error('Start a browser session (and log into bilibili) before running unfollow');\n}","typeGuard":"function hasBrowserPage(ctx) {\n  return ctx != null && typeof ctx === 'object' && typeof ctx.page === 'object' && ctx.page !== null;\n}","tryCatchPattern":"try {\n  await runCommand('bilibili unfollow', { target });\n} catch (err) {\n  if (err instanceof CommandExecutionError && /Browser session required/.test(err.message)) {\n    await openBrowserSession();\n    await runCommand('bilibili unfollow', { target }); // retry once\n  } else throw err;\n}","preventionTips":["Always start the interactive browser session before browser-dependent commands","Check session liveness (page != null) in wrapper scripts","Avoid running unfollow in CI/headless contexts where no session exists","Handle session expiry by reopening the session between long-running batch jobs"],"tags":["browser-session","authentication","bilibili"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}