jackwener/OpenCLI · error · ArgumentError
Unsupported Nowcoder URL; expected /discuss/<content-id> or
Error message
Unsupported Nowcoder URL; expected /discuss/<content-id> or /feed/main/detail/<moment-uuid>
What it means
parseNowcoderPostTarget accepts a numeric content ID, a moment UUID, or a canonical https://www.nowcoder.com URL. After passing the scheme/host checks, the URL pathname must match either /discuss/<content-id> (positive integer) or /feed/main/detail/<32-hex-char uuid>. Any other well-formed nowcoder.com URL path throws this ArgumentError, because the CLI cannot determine which post detail endpoint to call.
Source
Thrown at clis/nowcoder/posts.js:198
if (UUID_PATTERN.test(value)) return { post_type: 'moment', value: value.toLowerCase() };
let url;
try {
url = new URL(value);
}
catch {
throw new ArgumentError('nowcoder detail requires a numeric content ID, moment UUID, or canonical Nowcoder URL');
}
const host = url.hostname.toLowerCase();
if (url.protocol !== 'https:' || url.username || url.password || url.port || url.hash
|| (host !== 'nowcoder.com' && host !== 'www.nowcoder.com')) {
throw new ArgumentError('nowcoder detail only accepts canonical https://www.nowcoder.com post URLs');
}
const content = url.pathname.match(/^\/discuss\/([1-9]\d*)\/?$/);
if (content) return { post_type: 'content', value: content[1] };
const moment = url.pathname.match(/^\/feed\/main\/detail\/([0-9a-f]{32})\/?$/i);
if (moment) return { post_type: 'moment', value: moment[1].toLowerCase() };
throw new ArgumentError('Unsupported Nowcoder URL; expected /discuss/<content-id> or /feed/main/detail/<moment-uuid>');
}
export function projectNowcoderDetail(data, target) {
if (!isRecord(data) || !isRecord(data.frequencyData)) throw new CommandExecutionError('Nowcoder detail returned malformed post data');
const isContent = target.post_type === 'content';
const expectedEntityType = isContent ? CONTENT_ENTITY_TYPE : MOMENT_TYPE;
if (data.entityType !== expectedEntityType) throw new CommandExecutionError('Nowcoder detail returned a mismatched post entity type');
const uuid = requiredUuid(data.uuid, `${target.post_type} uuid`);
const entityId = requiredId(data.entityId, `${target.post_type} entity id`);
const id = isContent ? requiredId(data.id, 'content id') : uuid;
if (isContent ? id !== target.value : uuid !== target.value) throw new CommandExecutionError('Nowcoder detail returned a different post identity');
if (!isContent && entityId !== requiredId(data.id, 'moment id')) throw new CommandExecutionError('Nowcoder detail returned mismatched moment entity ids');
const expectedAuthorId = isContent ? data.authorId : data.userId;
const body = cleanBody(isContent ? data.richText : data.content, `${target.post_type} detail body`);
return {
post_type: target.post_type,
id,
uuid,View on GitHub (pinned to 49907e53dc)
Solutions
- Use a canonical URL of the form https://www.nowcoder.com/discuss/<numeric-id> or https://www.nowcoder.com/feed/main/detail/<32-hex-uuid>.
- Alternatively pass just the numeric content ID or the moment UUID string instead of a URL.
- Check the URL for extra path segments, leading zeros, or non-hex characters and correct them.
- If the post is not a discuss post or a feed moment, it is not supported — locate the discuss/feed version of the content.
Example fix
// before nowcoder detail "https://www.nowcoder.com/interview/ai/index" // after nowcoder detail "https://www.nowcoder.com/discuss/70123456"
Defensive patterns
Strategy: validation
Validate before calling
function isCanonicalNowcoderUrl(value) {
if (!/^\d+$/.test(value)) return true; // bare IDs/UUIDs are fine
try {
const url = new URL(value);
const okHost = ['nowcoder.com', 'www.nowcoder.com'].includes(url.hostname.toLowerCase());
const okPath = /^\/discuss\/[1-9]\d*\/?$/.test(url.pathname)
|| /^\/feed\/main\/detail\/[0-9a-f]{32}\/?$/i.test(url.pathname);
return url.protocol === 'https:' && okHost && okPath;
} catch { return true; }
} Type guard
function isNowcoderDiscussOrFeedUrl(v) {
return typeof v === 'string' && (/^https:\/\/(www\.)?nowcoder\.com\/discuss\/[1-9]\d*\/?$/.test(v)
|| /^https:\/\/(www\.)?nowcoder\.com\/feed\/main\/detail\/[0-9a-f]{32}\/?$/i.test(v));
} Try / catch
try {
await nowcoderDetail(target);
} catch (err) {
if (err instanceof ArgumentError && /Unsupported Nowcoder URL/.test(err.message)) {
console.error('Pass /discuss/<id>, /feed/main/detail/<uuid>, or a bare ID/UUID:', err.message);
} else throw err;
} Prevention
- Copy URLs directly from the post's canonical page (discuss/ or feed/main/detail/ routes).
- Prefer passing the bare numeric ID or 32-char moment UUID instead of a URL.
- Strip query strings and short-link redirects before passing a URL.
- Validate the URL shape with a regex in wrapper scripts before invoking the CLI.
When it happens
Trigger: Calling nowcoder detail with a nowcoder.com URL whose path is neither /discuss/<numeric-id> nor /feed/main/detail/<32-hex uuid> — e.g. a /interview/main/... link, a /discuss/ path with a non-numeric or zero-padded id (012345), a /feed/main/detail/ uuid that is not exactly 32 hex chars, or a URL with a query string altering the expectation of a trailing path segment.
Common situations: Pasting a Nowcoder link copied from the mobile app or a share dialog that uses a different route format; using a shortened or relative link; passing a URL for another nowcoder product page (jobs, campus, interview questions); typos in the URL; leading zeros or URL-encoded IDs in /discuss/ links.
Related errors
- 1688 item expects an offer URL or offer ID
- Invalid 1688 store URL
- Invalid 1688 URL
- ${label} must be a non-negative integer, got ${JSON.stringif
- limit must be a positive integer
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/90c8395710b713a5.
Report an issue: GitHub.