{"record":{"id":"b965a06d185f0b1b","repo":"jackwener/OpenCLI","slug":"bilibili-user-mid-is-blocked-unblock-first-bef","errorCode":null,"errorMessage":"Bilibili user ${mid} is blocked; unblock first before following.","messagePattern":"Bilibili user (.+?) is blocked; unblock first before following\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/follow.js","lineNumber":74,"sourceCode":"        },\n    ],\n    columns: ['mid', 'name', 'status', 'url'],\n    func: async (page, kwargs) => {\n        if (!page) {\n            throw new CommandExecutionError('Browser session required for bilibili follow');\n        }\n        const mid = await resolveTargetMid(page, kwargs.target);\n        const self = await getSelfUid(page);\n        if (mid === self) {\n            throw new ArgumentError('Cannot follow yourself');\n        }\n        const attribute = await fetchRelationAttribute(page, mid);\n        const url = `https://space.bilibili.com/${mid}`;\n        if (attribute === 2 || attribute === 6) {\n            return [{ mid, name: '', status: 'already-following', url }];\n        }\n        if (attribute === 128) {\n            throw new CommandExecutionError(\n                `Bilibili user ${mid} is blocked; unblock first before following.`,\n            );\n        }\n        // act=1 follow, act=2 unfollow. re_src=11 is the community-standard\n        // \"web\" source value used by third-party libs (bilibili-api-python etc.);\n        // omitting it makes the modify API reject with a vague code.\n        const payload = await apiPost(page, '/x/relation/modify', {\n            params: { fid: mid, act: 1, re_src: 11 },\n        });\n        requireOkPayload(payload, 'relation modify');\n        await waitForRelation(page, mid, (nextAttribute) => nextAttribute === 2 || nextAttribute === 6, 'following');\n        return [{ mid, name: '', status: 'followed', url }];\n    },\n});\n","sourceCodeStart":56,"sourceCodeEnd":89,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/follow.js#L56-L89","documentation":"fetchRelationAttribute returns the relation attribute byte; 128 means the target has blocked you, and attribute 2/6 would mean already following. Because Bilibili rejects follow requests toward users who blocked you, the command fails fast with this explicit CommandExecutionError telling you to unblock first (you cannot unblock someone else's block — it means the relationship is blocked from your side's block list context per this message).","triggerScenarios":"Running bilibili follow against a mid whose relation attribute is exactly 128 (blocked state).","commonSituations":"Attempting to re-follow a user you previously blocked, following someone after a dispute, batch scripts carrying stale target lists.","solutions":["Remove the block via bilibili.com (or the block API) for that user, then retry the follow.","Skip this user in batch jobs — the follow cannot succeed while the block exists.","Check the attribute first with a relation query before attempting follow in automation."],"exampleFix":"// before\nawait follow(mid);\n// after\nconst attr = await fetchRelationAttribute(page, mid);\nif (attr === 128) throw new Error(`skip ${mid}: blocked`);\nawait follow(mid);","handlingStrategy":"try-catch","validationCode":"const attr = await fetchRelationAttribute(page, mid);\nif (attr === 128) throw new Error(`${mid} is blocked; cannot follow until unblocked`);\nif (attr === 2 || attr === 6) console.log(`${mid} already followed`);","typeGuard":"function isBlockableRelation(attr) {\n  return typeof attr === 'number' && attr !== 2 && attr !== 6 && attr !== 128;\n}","tryCatchPattern":"try {\n  await follow(mid);\n} catch (e) {\n  if (String(e.message).includes('is blocked')) {\n    console.warn(`skipping ${mid}: blocked relationship`);\n    return; // do not retry until unblocked\n  }\n  throw e;\n}","preventionTips":["Query relation attribute before following in automation","Do not retry on 128 — it is deterministic, not transient","Keep target lists clean of blocked users","Handle already-following (2/6) as success to stay idempotent"],"tags":["bilibili","relation","precondition"],"backgroundTag":"blocked-user-precondition","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}