jackwener/OpenCLI · error · CommandExecutionError
No assistant reply found in Qianwen chat.
Error message
No assistant reply found in Qianwen chat.
What it means
CommandExecutionError thrown when waitForAnswer finished without a timeout or auth failure but returned no assistant object — the reply could not be located/parsed in the chat DOM.
Source
Thrown at clis/qwen/ask.js:79
// Anchor on the visible transcript BEFORE sending so waitForAnswer can
// bind the reply to the newly sent prompt instead of an older answer.
const baselineAnchor = await getBaselineChatAnchor(page);
const send = await sendMessage(page, prompt);
if (!send?.ok) {
if (await hasLoginGate(page)) throw authRequired();
throw new CommandExecutionError(send?.reason || 'Failed to send Qianwen prompt');
}
const result = await waitForAnswer(page, prompt, timeout, baselineAnchor);
if (result.status === 'auth_required') throw authRequired();
if (result.status === 'timeout') {
throw new TimeoutError('qianwen ask', timeout, 'No Qianwen reply observed before timeout. Retry with --timeout increased.');
}
const assistant = result.assistant;
if (!assistant) {
throw new CommandExecutionError('No assistant reply found in Qianwen chat.');
}
const answer = wantMarkdown && assistant.html
? (bubbleHtmlToMarkdown(assistant.html) || assistant.text)
: assistant.text;
return [
{ Role: 'User', Text: prompt },
{ Role: 'Assistant', Text: answer },
];
},
});
async function getBaselineChatAnchor(page) {
const bubbles = await getMessageBubbles(page);
const lastBubbleId = bubbles.length ? bubbles[bubbles.length - 1].id : '';
let lastAssistantId = '';
for (let i = bubbles.length - 1; i >= 0; i -= 1) {
if (bubbles[i].role === 'Assistant') {
lastAssistantId = bubbles[i].id;View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the page DOM after failure and update the assistant-bubble selector used by waitForAnswer.
- Retry without --markdown to rule out HTML->markdown conversion producing empty output.
- Check whether Qianwen returned a refusal/error card and adjust prompting.
- Upgrade the library if a newer release adapts to the new UI.
Example fix
// before
const ans = await qwenAsk(page, { prompt: q, markdown: true });
// after
let ans;
try { ans = await qwenAsk(page, { prompt: q, markdown: true }); }
catch (e) {
if (String(e.message).includes('No assistant reply')) {
ans = await qwenAsk(page, { prompt: q, markdown: false });
} else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
// no pre-call check possible; mitigate by disabling markdown conversion path
const opts = { prompt, markdown: false }; Type guard
function isNoReplyError(e) {
return e instanceof CommandExecutionError && e.message.includes('No assistant reply');
} Try / catch
try {
ans = await qwenAsk(page, { prompt, markdown: true });
} catch (e) {
if (isNoReplyError(e)) {
ans = await qwenAsk(page, { prompt, markdown: false });
} else { throw e; }
} Prevention
- Retry without --markdown to isolate conversion issues
- Update the library after Qianwen UI changes
- Capture a DOM snapshot on failure for selector debugging
- Avoid prompting that triggers refusal/error cards
When it happens
Trigger: waitForAnswer returns with result.assistant undefined: the reply bubble selector mismatched, the chat DOM structure changed, the response was an error card instead of an answer, or bubbleHtmlToMarkdown produced no usable text path.
Common situations: Qianwen frontend update renaming reply container classes; answer rendered as an error/filtered-content notice; streaming UI state the extractor does not handle; wantMarkdown conversion failing silently leaving empty text.
Related errors
- Failed to extract Booking.com cards: ${err?.message || err}
- coupang add-to-cart evaluation failed: ${error?.message || e
- coupang search
- coupang search extraction failed: ${error?.message || error}
- Ctrip cruise port page did not render (state=${String(portWa
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4ae05b223b01ecea.
Report an issue: GitHub.