jackwener/OpenCLI · error · ArgumentError
xiaohongshu/unfollow: profile URL must be an exact https://*
Error message
xiaohongshu/unfollow: profile URL must be an exact https://*.xiaohongshu.com URL
What it means
assertUserId accepts URL-shaped input only if it is an https URL on xiaohongshu.com or a subdomain. This ArgumentError is thrown when the URL parses but uses a non-https protocol or points at a non-Xiaohongshu host. The library restricts URL input to exact https://*.xiaohongshu.com profile pages to avoid acting on spoofed or redirector links.
Source
Thrown at clis/xiaohongshu/unfollow.js:46
function requireActionResult(payload, context) {
const inner = unwrapEvaluateResult(payload);
if (!inner || typeof inner !== 'object' || Array.isArray(inner) || typeof inner.ok !== 'boolean') {
throw new CommandExecutionError(`xiaohongshu/unfollow: malformed ${context} payload`);
}
return inner;
}
function assertUserId(raw) {
const input = String(raw ?? '').trim();
if (/^https?:\/\//i.test(input)) {
let parsed;
try {
parsed = new URL(input);
} catch {
throw new ArgumentError('xiaohongshu/unfollow: invalid profile URL');
}
if (parsed.protocol !== 'https:' || !isXiaohongshuHost(parsed.hostname)) {
throw new ArgumentError('xiaohongshu/unfollow: profile URL must be an exact https://*.xiaohongshu.com URL');
}
const match = parsed.pathname.match(/^\/user\/profile\/([a-zA-Z0-9]{8,32})\/?$/);
if (!match) {
throw new ArgumentError('xiaohongshu/unfollow: profile URL must be /user/profile/<userId>');
}
return match[1];
}
const userId = normalizeXhsUserId(raw);
if (!userId || !USER_ID_RE.test(userId)) {
throw new ArgumentError(
'xiaohongshu/unfollow: user-id must be a Xiaohongshu user ID (e.g. 5d8f88dc0000000001005d3a) or full profile URL',
);
}
return userId;
}
/**
* Click the 已关注 / 已互关 button on the profile (idempotent if not following).View on GitHub (pinned to 49907e53dc)
Solutions
- Upgrade the URL to https:// : 'https://www.xiaohongshu.com/user/profile/<userId>'
- Resolve short links (xhslink.com) in a browser and copy the final canonical xiaohongshu.com URL
- Alternatively pass only the raw user ID (8-32 alphanumeric characters) instead of a URL
- Check for typos in the hostname (xiaohongshu.com, not xiaohongshu.co or a mirror domain)
Example fix
// before $ xiaohongshu unfollow 'http://www.xiaohongshu.com/user/profile/5d8f88dc0000000001005d3a' // after $ xiaohongshu unfollow 'https://www.xiaohongshu.com/user/profile/5d8f88dc0000000001005d3a'
Defensive patterns
Strategy: validation
Validate before calling
function assertCanonicalXhsUrl(input) {
const u = new URL(String(input).trim());
if (u.protocol !== 'https:' || !(u.hostname === 'xiaohongshu.com' || u.hostname.endsWith('.xiaohongshu.com'))) {
throw new Error('URL must be https://*.xiaohongshu.com: ' + input);
}
return u;
} Type guard
function isXhsUrl(input) {
try { const u = new URL(String(input).trim());
return u.protocol === 'https:' && (u.hostname === 'xiaohongshu.com' || u.hostname.endsWith('.xiaohongshu.com'));
} catch { return false; }
} Try / catch
try { await cli.unfollow({ 'user-id': url }); } catch (e) { if (String(e.message).includes('https://*.xiaohongshu.com')) { /* resolve short link or upgrade to https and retry once */ } else throw e; } Prevention
- Always use https:// canonical xiaohongshu.com profile URLs
- Expand xhslink.com short links before passing them
- Never pass third-party or mirror domains
- Pass the raw user ID to bypass URL checks entirely
When it happens
Trigger: Passing 'http://www.xiaohongshu.com/user/profile/<id>' (http, not https); passing a different site's URL such as 'https://example.com/user/profile/abc' or 'https://xhslink.com/xyz' (short-link domains are rejected); passing 'https://www.xiaohongshu.com.evil.com/...'.
Common situations: Copying an http:// link from an old message or email; using a xiaohongshu short-link (xhslink.com) or mobile-scheme link (xhsdiscover://) instead of the canonical web profile URL; building the URL with a configurable base host that points elsewhere.
Related errors
- xiaoe URL must use https (got ${parsed.protocol.replace(':',
- 1688 item expects an offer URL or offer ID
- Invalid 1688 store URL
- Invalid 1688 URL
- Expected an exact BVID or bilibili.com video URL, for exampl
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/07be47a0582f0124.
Report an issue: GitHub.