jackwener/OpenCLI · error · ArgumentError

Answer ID must be a numeric id, a Zhihu answer URL, or answe

Error message

Answer ID must be a numeric id, a Zhihu answer URL, or answer:<qid>:<aid>

What it means

answer-detail uses the same parseAnswerTarget validation as answer-comments: the id argument must be a numeric answer id, a Zhihu answer URL, or answer:<qid>:<aid>, otherwise this ArgumentError is thrown with a usage example. It is thrown before any browser navigation.

Source

Thrown at clis/zhihu/answer-detail.js:41

    }
}

cli({
    site: 'zhihu',
    name: 'answer-detail',
    access: 'read',
    description: '知乎单个回答完整内容(按 answer ID 获取)',
    domain: 'www.zhihu.com',
    strategy: Strategy.COOKIE,
    args: [
        { name: 'id', required: true, positional: true, help: 'Answer ID, full Zhihu answer URL, or typed target (answer:<qid>:<aid>)' },
        { name: 'max-content', type: 'int', default: 0, help: 'Optional cap on stripped content length in characters (0 = no truncation, return the full answer)' },
    ],
    columns: ['id', 'author', 'votes', 'comments', 'question_id', 'question_title', 'url', 'created_at', 'updated_at', 'content'],
    func: async (page, kwargs) => {
        const target = parseAnswerTarget(kwargs.id);
        if (!target) {
            throw new ArgumentError(
                'Answer ID must be a numeric id, a Zhihu answer URL, or answer:<qid>:<aid>',
                'Example: opencli zhihu answer-detail 1937205528846655537',
            );
        }
        const { answerId } = target;
        // `--max-content 0` (the default) means "no cap, return the
        // full stripped answer". Any positive value is an opt-in user
        // cap, mirroring the wikipedia `page` pattern — we never
        // silently truncate behind the user's back.
        const rawMaxContent = kwargs['max-content'];
        const maxContent = rawMaxContent == null ? 0 : Number(rawMaxContent);
        if (!Number.isInteger(maxContent) || maxContent < 0) {
            throw new ArgumentError(
                '--max-content must be a non-negative integer (0 = no cap, full content)',
                'Example: --max-content 2000',
            );
        }
        // Navigate to the answer page itself: this both seeds the

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a numeric answer id: opencli zhihu answer-detail 1937205528846655537
  2. Or pass the full answer URL containing /answer/<aid>
  3. Or use answer:<qid>:<aid> form
  4. Trim whitespace and strip URL fragments/query params before passing

Example fix

// before
opencli zhihu answer-detail https://zhuanlan.zhihu.com/p/999
// after
opencli zhihu answer-detail https://www.zhihu.com/question/123/answer/1937205528846655537
Defensive patterns

Strategy: validation

Validate before calling

const m = String(id).match(/answer\/(\d+)/) || String(id).match(/^answer:(\d+):(\d+)$/) || (/^\d+$/.test(String(id).trim()) ? [null, String(id).trim()] : null);
if (!m) throw new Error('answer-detail needs a numeric id, answer URL, or answer:<qid>:<aid>');

Type guard

const isAnswerDetailTarget = (v) => typeof v === 'string' && (/^\d+$/.test(v.trim()) || /\/answer\/\d+/.test(v) || /^answer:\d+:\d+$/.test(v.trim()));

Prevention

When it happens

Trigger: Passing a question id, an article (zhuanlan.zhihu.com) URL, a missing or empty id, or a malformed answer: prefix string to zhihu answer-detail.

Common situations: Mixing up question vs answer ids; pasting a pinned-comment or share link that isn't an /answer/ URL; whitespace or invisible characters in a copy-pasted id.

Related errors


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