jackwener/OpenCLI · error · CliError

COMMAND_EXEC

COMMAND_EXEC

Error message

${apiResult?.message || 'Failed to create answer'}

What it means

After answering a question, the CLI executes an in-page fetch to Zhihu's answer API. If the result is not ok (non-2xx status, unknown/missing created id, or any thrown message), it throws CliError('COMMAND_EXEC') carrying the API's error message. It means the answer was NOT created — the HTTP call failed or returned an unexpected payload.

Source

Thrown at clis/zhihu/answer.js:46

        await page.wait(3);
        const authorIdentity = await resolveCurrentUserIdentity(page);
        const apiResult = await page.evaluate(`(async () => {
            var questionId = ${JSON.stringify(target.id)};
            var content = ${JSON.stringify(payload)};
            var url = 'https://www.zhihu.com/api/v4/questions/' + questionId + '/answers';
            var resp = await fetch(url, {
                method: 'POST',
                credentials: 'include',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ content: content, reshipment_settings: 'disallowed' }),
            });
            var data = await resp.json();
            if (!resp.ok) return { ok: false, status: resp.status, message: data.error ? data.error.message : 'unknown error' };
            if (!data || !data.id) return { ok: false, status: resp.status, message: 'Answer API response did not include a created answer id' };
            return { ok: true, id: String(data.id), url: data.url || ('https://www.zhihu.com/question/' + questionId + '/answer/' + data.id) };
        })()`);
        if (!apiResult?.ok) {
            throw new CliError('COMMAND_EXEC', apiResult?.message || 'Failed to create answer');
        }
        return buildResultRow(`Answered question ${target.id}`, target.kind, rawTarget, 'created', {
            created_target: 'answer:' + target.id + ':' + apiResult.id,
            created_url: apiResult.url,
            author_identity: authorIdentity,
        });
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the embedded message (apiResult.message) for the HTTP status/error text and re-login with `opencli zhihu login` if it indicates 401/403 (expired z_c0 cookie).
  2. Wait and retry later if rate-limited; Zhihu throttles frequent answers.
  3. Verify the question is open and the target id is correct (`question:<id>`).
  4. Inspect the response status in the message; if the page shows a captcha/challenge, complete login/verification in the browser and retry.

Example fix

// before
throw new CliError('COMMAND_EXEC', apiResult?.message || 'Failed to create answer');
// after — caller side handling
try {
  await zhihuAnswer({ target, file });
} catch (e) {
  if (/401|403/.test(e.message)) await refreshZhihuLogin();
  else if (/429|rate/i.test(e.message)) await sleep(60_000);
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!/^question:\d+$/.test(rawTarget)) throw new Error('target must be question:<id> before answering');

Type guard

function isApiResultOk(r) { return !!r && r.ok === true && typeof r.id === 'string'; }

Try / catch

try { await zhihuAnswer(args); } catch (e) { if (e.code === 'COMMAND_EXEC') { const m = /HTTP (\d+)/.exec(e.message); if (m && ['401','403'].includes(m[1])) await zhihuLogin(); else if (m && m[1] === '429') await sleep(60_000); } throw e; }

Prevention

When it happens

Trigger: The in-page fetch to create the answer returns resp.ok === false (rate limit, auth rejection, question closed, anti-spam challenge); the response JSON lacks an `id`; or the in-page promise rejects so apiResult.ok is false.

Common situations: z_c0 cookie expired so the API returns 401/403; posting too frequently triggers Zhihu rate limiting; the target question is closed or restricted; network proxy/firewall blocks the XHR inside the page.

Related errors


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