{"record":{"id":"a532ac00317fedac","repo":"jackwener/OpenCLI","slug":"bilibili-follow-target-must-be-a-valid-space-bilib","errorCode":null,"errorMessage":"bilibili follow target must be a valid space.bilibili.com/<uid> URL","messagePattern":"bilibili follow target must be a valid space\\.bilibili\\.com/<uid> URL","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/follow.js","lineNumber":28,"sourceCode":"import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\nimport { parseSpaceMidUrl, fetchRelationAttribute, waitForRelation } from './relation.js';\nimport { apiPost, getSelfUid, requireOkPayload, resolveUid } from './utils.js';\n\n/**\n * Pull a uid out of a `space.bilibili.com/<uid>` URL before falling back to the\n * generic resolver. `resolveUid` only handles bare digits or usernames; without\n * this short-circuit a profile URL would get sent to the user-search endpoint\n * and likely return nothing.\n */\nasync function resolveTargetMid(page, raw) {\n    const trimmed = String(raw ?? '').trim();\n    if (!trimmed) {\n        throw new ArgumentError('bilibili follow target cannot be empty');\n    }\n    if (/^(?:https?:\\/\\/)?space\\.bilibili\\.com\\//i.test(trimmed)) {\n        const mid = parseSpaceMidUrl(trimmed);\n        if (!mid) {\n            throw new ArgumentError('bilibili follow target must be a valid space.bilibili.com/<uid> URL');\n        }\n        return mid;\n    }\n    try {\n        return await resolveUid(page, trimmed);\n    } catch (error) {\n        if (error instanceof EmptyResultError) throw error;\n        throw new ArgumentError(\n            `Cannot resolve Bilibili target from input: ${trimmed}`,\n            error instanceof Error ? error.message : String(error),\n        );\n    }\n}\n\ncli({\n    site: 'bilibili',\n    name: 'follow',\n    access: 'write',","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/follow.js#L10-L46","documentation":"When the target looks like a space.bilibili.com URL, resolveTargetMid parses the mid out of it via parseSpaceMidUrl; if the parse fails it throws this ArgumentError instead of falling through to user search, because a malformed profile URL should never hit the search endpoint.","triggerScenarios":"Passing a string starting with space.bilibili.com/ that contains no numeric mid, e.g. 'space.bilibili.com/', 'https://space.bilibili.com/abc', or a URL with extra path segments the parser cannot handle.","commonSituations":"Copy-pasting a truncated profile URL, using a personalized space URL (custom domain or /name path), or editing a URL and deleting the numeric id.","solutions":["Use the canonical numeric URL form: https://space.bilibili.com/123456789.","If you only have a username, pass the username directly instead of a URL so it goes through resolveUid.","Extract the numeric uid manually and pass it as the target."],"exampleFix":"// before\nbilibili follow --target 'https://space.bilibili.com/dynamic'\n// after\nbilibili follow --target 'https://space.bilibili.com/9469745'","handlingStrategy":"validation","validationCode":"if (/^(?:https?:\\/\\/)?space\\.bilibili\\.com\\//i.test(target) && !/^\\d+$/.test(new URL(target.startsWith('http') ? target : 'https://' + target).pathname.split('/')[1] ?? '')) {\n  throw new Error('space URL must contain a numeric uid');\n}","typeGuard":"function isSpaceUidUrl(s) {\n  const m = /^(?:https?:\\/\\/)?space\\.bilibili\\.com\\/(\\d+)\\/?$/i.exec(s.trim());\n  return m !== null;\n}","tryCatchPattern":"try {\n  const mid = await resolveTargetMid(page, raw);\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('space.bilibili.com')) {\n    console.error(`'${raw}' is not a valid space URL; pass a numeric uid instead`);\n    return;\n  }\n  throw e;\n}","preventionTips":["Prefer passing the bare numeric uid","Copy the full canonical URL https://space.bilibili.com/<uid>","Strip tracking query params/extra paths before passing URLs"],"tags":["validation","argument-error","url-parsing"],"backgroundTag":"invalid-url-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}