jackwener/OpenCLI · error · ArgumentError

xiaohongshu/delete-note: invalid note URL

Error message

xiaohongshu/delete-note: invalid note URL

What it means

normalizeNoteId validates the note-id argument passed to the xiaohongshu/delete-note CLI. If the input is not a bare 24-hex-char note ID and not an https URL, it tries `new URL(raw)`; when that constructor throws (malformed URL), this ArgumentError is raised. It guards against silently proceeding with an unparseable URL string.

Source

Thrown at clis/xiaohongshu/delete-note.js:72

    return url.hostname.toLowerCase() === 'creator.xiaohongshu.com'
        && url.pathname.replace(/\/+$/, '') === '/statistics/note-detail';
}
function normalizeNoteId(input) {
    const raw = String(input ?? '').trim();
    if (!raw) {
        throw new ArgumentError('xiaohongshu/delete-note: note-id cannot be empty');
    }
    if (NOTE_ID_RE.test(raw))
        return raw.toLowerCase();
    if (!/^https:\/\//i.test(raw)) {
        throw new ArgumentError('xiaohongshu/delete-note: note-id must be a 24-character Xiaohongshu note ID or an exact Xiaohongshu note URL');
    }
    let url;
    try {
        url = new URL(raw);
    }
    catch {
        throw new ArgumentError('xiaohongshu/delete-note: invalid note URL');
    }
    if (url.protocol !== 'https:' || url.username || url.password || url.port || !isXiaohongshuHost(url.hostname)) {
        throw new ArgumentError('xiaohongshu/delete-note: note URL must be an exact https://*.xiaohongshu.com URL');
    }
    const queryId = url.searchParams.get('noteId') || url.searchParams.get('note_id');
    if (queryId && NOTE_ID_RE.test(queryId) && isSupportedQueryNoteUrl(url))
        return queryId.toLowerCase();
    const pathMatch = url.pathname.match(/^\/(?:explore|note|search_result|discovery\/item)\/([0-9a-f]{24})\/?$/i)
        || url.pathname.match(/^\/user\/profile\/[^/?#]+\/([0-9a-f]{24})\/?$/i);
    if (pathMatch)
        return pathMatch[1].toLowerCase();
    throw new ArgumentError('xiaohongshu/delete-note: note URL must contain a 24-character note ID');
}
function buildLocateAndMaybeDeleteScript(noteId, shouldClick) {
    return `
      (cfg => {
        const { targetId, shouldClick } = cfg;
        const isVisible = (el) => !!el && el.offsetParent !== null;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the exact argument with `node -e "new URL(process.argv[1])" '<your-url>'` to see what is malformed
  2. Re-copy the note URL directly from the browser address bar (fully expanded, including https://)
  3. If you have the note ID itself, pass the 24-hex-character ID instead of a URL
  4. Quote the URL in the shell so special characters (?, &, #) are not consumed by the shell

Example fix

// before
opencli xiaohongshu delete-note --note 'https:/xiaohongshu.com/explore/abc...'
// after
opencli xiaohongshu delete-note --note 'https://www.xiaohongshu.com/explore/0123456789abcdef01234567'
Defensive patterns

Strategy: validation

Validate before calling

function isValidNoteUrlArg(raw) {
  const s = String(raw ?? '').trim();
  if (/^[0-9a-f]{24}$/i.test(s)) return true;
  if (!/^https:\/\//i.test(s)) return false;
  try { new URL(s); return true; } catch { return false; }
}
if (!isValidNoteUrlArg(noteArg)) throw new Error('argument is not a valid note ID or URL');

Type guard

function isParsableUrl(s) {
  if (typeof s !== 'string') return false;
  try { new URL(s); return true; } catch { return false; }
}

Try / catch

try {
  await cli('xiaohongshu', 'delete-note', { note: noteArg });
} catch (err) {
  if (err instanceof ArgumentError && err.message.includes('invalid note URL')) {
    console.error('The --note argument is not a parseable URL; pass a 24-char ID or a full https://...xiaohongshu.com link.');
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a --note argument that starts with 'https://' (or http) but is not parseable by the WHATWG URL parser — e.g. 'https://', 'https:/xiaohongshu.com/explore/x', a URL with unescaped spaces or control characters, or a truncated/mangled URL copied from a chat or terminal that wrapped lines.

Common situations: Copy-pasting a note link that got line-wrapped in a terminal or chat app; missing characters after shell escaping; hand-editing a URL and introducing typos; shell globbing or brace expansion mangling the URL before it reaches the CLI.

Related errors


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