jackwener/OpenCLI · error · ArgumentError

${message}

Error message

${message}

What it means

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.

Source

Thrown at clis/xiaohongshu/note-helpers.js:56

 */
export function buildNoteUrl(input, options = {}) {
    const {
        allowShortLink = false,
        commandName = 'xiaohongshu note',
        cookieRoot = 'xiaohongshu.com',
        signedUrlHint = XHS_SIGNED_URL_HINT,
    } = options;
    const trimmed = input.trim();
    const message = `${commandName} now requires a full signed URL`;
    const hint = allowShortLink
        ? `${signedUrlHint} For downloads, xhslink short links are also supported.`
        : signedUrlHint;

    if (/^https?:\/\//.test(trimmed)) {
        if (isShortLink(trimmed)) {
            if (allowShortLink)
                return trimmed;
            throw new ArgumentError(message, hint);
        }
        try {
            const url = new URL(trimmed);
            const xsecToken = url.searchParams.get('xsec_token')?.trim();
            if (isHostMatch(url.hostname, cookieRoot) && isSupportedNotePath(url.pathname) && xsecToken) {
                return trimmed;
            }
        }
        catch { }
        throw new ArgumentError(message, hint);
    }
    throw new ArgumentError(message, hint);
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Resolve the short link by opening it in a browser and copying the full www.xiaohongshu.com/explore/... URL including xsec_token.
  2. Get the note URL from search results or user-profile context so it carries xsec_token.
  3. If using the download command, verify you are on a code path that sets allowShortLink: true.
  4. Use the bare note ID only where the API still accepts it — for note detail it no longer resolves reliably.

Example fix

// before
buildNoteUrl('https://xhslink.com/a1B2c3');
// after
buildNoteUrl('https://www.xiaohongshu.com/explore/<id>?xsec_token=<token>', { commandName: 'xiaohongshu note' });
Defensive patterns

Strategy: validation

Validate before calling

const input = 'https://xhslink.com/a1B2c3';
if (/^https?:\/\/xhslink\.com\//i.test(input)) {
  throw new Error('resolve the short link to a full xiaohongshu.com URL with xsec_token first');
}

Type guard

function isFullSignedNoteUrl(input) {
  if (/^https?:\/\/xhslink\.com\//i.test(input)) return false;
  try {
    const u = new URL(input);
    return /(^|\.)xiaohongshu\.com$/.test(u.hostname)
      && /^\/(?:explore|note|search_result|discovery\/item)\/[a-f0-9]+/i.test(u.pathname)
      && !!u.searchParams.get('xsec_token')?.trim();
  } catch { return false; }
}

Try / catch

try {
  await note(shortUrl);
} catch (err) {
  if (err instanceof ArgumentError && err.message.includes('full signed URL')) {
    console.error('Open the short link in a browser and pass the resolved URL with xsec_token.');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling a note command (e.g. 'xiaohongshu note <url>') with an https://xhslink.com/... URL when allowShortLink is false.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/4ce5abf3e6eafe63. Report an issue: GitHub.