{"record":{"id":"4ce5abf3e6eafe63","repo":"jackwener/OpenCLI","slug":"message-4ce5ab","errorCode":null,"errorMessage":"${message}","messagePattern":"\\$\\{message\\}","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/note-helpers.js","lineNumber":56,"sourceCode":" */\nexport function buildNoteUrl(input, options = {}) {\n    const {\n        allowShortLink = false,\n        commandName = 'xiaohongshu note',\n        cookieRoot = 'xiaohongshu.com',\n        signedUrlHint = XHS_SIGNED_URL_HINT,\n    } = options;\n    const trimmed = input.trim();\n    const message = `${commandName} now requires a full signed URL`;\n    const hint = allowShortLink\n        ? `${signedUrlHint} For downloads, xhslink short links are also supported.`\n        : signedUrlHint;\n\n    if (/^https?:\\/\\//.test(trimmed)) {\n        if (isShortLink(trimmed)) {\n            if (allowShortLink)\n                return trimmed;\n            throw new ArgumentError(message, hint);\n        }\n        try {\n            const url = new URL(trimmed);\n            const xsecToken = url.searchParams.get('xsec_token')?.trim();\n            if (isHostMatch(url.hostname, cookieRoot) && isSupportedNotePath(url.pathname) && xsecToken) {\n                return trimmed;\n            }\n        }\n        catch { }\n        throw new ArgumentError(message, hint);\n    }\n    throw new ArgumentError(message, hint);\n}\n","sourceCodeStart":38,"sourceCodeEnd":70,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/note-helpers.js#L38-L70","documentation":"buildNoteUrl throws ArgumentError when given an xhslink.com short link while options.allowShortLink is false. Xiaohongshu note pages now require signed URLs (with xsec_token) for reliable access; short links are only accepted for download commands that opt in. The message names the command and the hint explains what URL format is accepted.","triggerScenarios":"Calling a note command (e.g. 'xiaohongshu note <url>') with an https://xhslink.com/... URL when allowShortLink is false.","commonSituations":"Copying a share short link from the XHS app instead of the full note URL from search results; older scripts that predate the signed-URL requirement.","solutions":["Resolve the short link by opening it in a browser and copying the full www.xiaohongshu.com/explore/... URL including xsec_token.","Get the note URL from search results or user-profile context so it carries xsec_token.","If using the download command, verify you are on a code path that sets allowShortLink: true.","Use the bare note ID only where the API still accepts it — for note detail it no longer resolves reliably."],"exampleFix":"// before\nbuildNoteUrl('https://xhslink.com/a1B2c3');\n// after\nbuildNoteUrl('https://www.xiaohongshu.com/explore/<id>?xsec_token=<token>', { commandName: 'xiaohongshu note' });","handlingStrategy":"validation","validationCode":"const input = 'https://xhslink.com/a1B2c3';\nif (/^https?:\\/\\/xhslink\\.com\\//i.test(input)) {\n  throw new Error('resolve the short link to a full xiaohongshu.com URL with xsec_token first');\n}","typeGuard":"function isFullSignedNoteUrl(input) {\n  if (/^https?:\\/\\/xhslink\\.com\\//i.test(input)) return false;\n  try {\n    const u = new URL(input);\n    return /(^|\\.)xiaohongshu\\.com$/.test(u.hostname)\n      && /^\\/(?:explore|note|search_result|discovery\\/item)\\/[a-f0-9]+/i.test(u.pathname)\n      && !!u.searchParams.get('xsec_token')?.trim();\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await note(shortUrl);\n} catch (err) {\n  if (err instanceof ArgumentError && err.message.includes('full signed URL')) {\n    console.error('Open the short link in a browser and pass the resolved URL with xsec_token.');\n  } else throw err;\n}","preventionTips":["Never pass xhslink short links to note/comment commands — only downloads accept them.","Always carry the xsec_token from the source page when copying URLs.","Resolve short links once and store the expanded signed URL."],"tags":["xiaohongshu","argument-validation","signed-url"],"backgroundTag":"missing-signed-url-token","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}