jackwener/OpenCLI · warning · EmptyResultError
zhihu user
Error message
zhihu user
What it means
EmptyResultError with resource 'zhihu user' is thrown when the in-page fetch returns HTTP 404 — i.e. no Zhihu user exists for the given slug. It is the 'not found' branch of the user profile command's error handling.
Source
Thrown at clis/zhihu/user.js:40
const apiUrl = `https://www.zhihu.com/api/v4/members/${encodeURIComponent(slug)}?include=${encodeURIComponent(INCLUDE)}`;
const data = unwrapEvaluateResult(await page.evaluate(`
(async () => {
try {
const r = await fetch(${JSON.stringify(apiUrl)}, { credentials: 'include' });
if (!r.ok) return { __httpError: r.status };
return await r.json();
} catch (err) {
return { __fetchError: err?.message || String(err) };
}
})()
`));
if (!data || typeof data !== 'object' || Array.isArray(data) || data.__httpError || data.__fetchError) {
const status = data?.__httpError;
if (status === 401 || status === 403) {
throw new AuthRequiredError('www.zhihu.com', 'Failed to fetch Zhihu user profile');
}
if (status === 404) {
throw new EmptyResultError('zhihu user', `No Zhihu user was found for ${slug}.`);
}
throw new CommandExecutionError(status ? `Zhihu user request failed (HTTP ${status})` : 'Zhihu user request failed', data?.__fetchError ? String(data.__fetchError) : 'Try again later or rerun with -v');
}
if (!data.url_token || !data.id || !data.name) {
throw new CommandExecutionError('Zhihu user response missing identity fields', 'Zhihu may have changed its API shape');
}
return [{
url_token: String(data.url_token || ''),
name: String(data.name || ''),
headline: String(data.headline || ''),
followers: data.follower_count ?? 0,
following: data.following_count ?? 0,
answers: data.answer_count ?? 0,
articles: data.articles_count ?? 0,
voteup: data.voteup_count ?? 0,
url: data.url_token ? `https://www.zhihu.com/people/${data.url_token}` : '',
}];
},View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the url_token in the browser by visiting https://www.zhihu.com/people/<slug>
- Re-resolve the user's current url_token (it can change after renames)
- Check for typos or truncation in the slug argument
- Confirm the account still exists and wasn't deactivated
Example fix
// before node cli.js zhihu user wen-jie-1647 // after node cli.js zhihu user wen-jie-16-47
Defensive patterns
Strategy: validation
Validate before calling
// before calling, sanity-check the slug format and existence in the browser
const slugOk = typeof slug === 'string' && /^[A-Za-z0-9_-]+$/.test(slug);
if (!slugOk) throw new Error('Invalid url_token format: ' + slug);
// existence check: fetch https://www.zhihu.com/people/<slug> and expect 200 Type guard
const isPlausibleSlug = (s) => typeof s === 'string' && s.length > 0 && /^[A-Za-z0-9_-]+$/.test(s);
Try / catch
try {
const user = await fetchZhihuUser(slug);
} catch (e) {
if (e instanceof EmptyResultError) {
console.warn(`No Zhihu user for ${slug}; skipping`);
return null;
}
throw e;
} Prevention
- Verify url_tokens by opening https://www.zhihu.com/people/<slug> before automation
- Re-resolve slugs periodically — users can rename their url_token
- Treat EmptyResultError as 'skip this user' in batch jobs
- Don't derive slugs from display names
When it happens
Trigger: Requesting a profile whose url_token does not exist: a typo in the slug, a user who renamed their url_token, a deactivated/deleted account, or passing a display name instead of the url_token that happens to 404.
Common situations: Hardcoded slugs that broke after the user renamed their profile; scraping historical usernames; copying an incomplete URL fragment as the slug.
Related errors
- zhihu answer-detail
- NOT_FOUND
- NOT_FOUND
- bilibili creator-stats ${bvid}
- Chess.com returned 404 for ${url}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3048149012e58011.
Report an issue: GitHub.