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
- Inspect the exact argument with `node -e "new URL(process.argv[1])" '<your-url>'` to see what is malformed
- Re-copy the note URL directly from the browser address bar (fully expanded, including https://)
- If you have the note ID itself, pass the 24-hex-character ID instead of a URL
- 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
- Always quote note URLs in the shell so ?, &, and # are not interpreted
- Re-copy URLs directly from the browser address bar rather than from chat/terminal output where they may wrap
- Prefer passing the bare 24-character note ID, which skips URL parsing entirely
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
- --url must be a Discord channel URL like https://discord.com
- --url must be a Discord thread/post URL like https://discord
- id not a valid Grok URL (got "${input}")
- Invalid Instagram URL: ${raw}
- job-id must be a Midjourney UUID or https://www.midjourney.c
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ee492e302f2a94c4.
Report an issue: GitHub.