jackwener/OpenCLI · warning · CommandExecutionError
Copy button not visible
Error message
Copy button not visible
What it means
When copy-message runs with click-button=true, it invokes clickBySvgNameScript('Copy') on the last assistant turn; if the in-page script cannot find/click a Copy button, CommandExecutionError is thrown. The message (or clickRes.reason) indicates the copy control was not present or not clickable at that moment.
Source
Thrown at clis/kimi/chat.js:346
browser: true,
siteSession: 'persistent',
navigateBefore: false,
args: [
{ name: 'conv', required: false, help: 'Chat id or URL (navigates there before reading)' },
{ name: 'click-button', type: 'boolean', default: false, help: 'Also click in-UI Copy button (writes to clipboard)' },
],
columns: CHAT_COLUMNS,
func: async (page, kwargs) => {
await maybeNavigateConv(page, kwargs?.conv);
const turns = await readKimiTurns(page);
const assistantTurns = turns.filter((t) => t.role === 'Assistant');
if (!assistantTurns.length) {
throw new EmptyResultError('kimi copy-message', 'No assistant message visible.');
}
const last = assistantTurns[assistantTurns.length - 1];
if (kwargs?.['click-button'] === true || kwargs?.['click-button'] === 'true') {
const clickRes = await page.evaluate(clickBySvgNameScript('Copy'));
if (!clickRes?.ok) throw new CommandExecutionError(clickRes?.reason || 'Copy button not visible', '');
}
return [
{ Field: 'Length', Value: String((last.text || '').length) + ' chars' },
{ Field: 'ClipboardClicked', Value: (kwargs?.['click-button'] === true || kwargs?.['click-button'] === 'true') ? 'yes' : 'no' },
{ Field: 'Text', Value: last.text || '' },
];
},
});
// -------- regenerate --------
cli({
site: 'kimi',
name: 'regenerate',
access: 'write',
description: 'Click Refresh (Kimi\'s regenerate button) on the last assistant message. Pass --conv <id> to target a specific chat.',
domain: KIMI_DOMAIN,
strategy: Strategy.COOKIE,
browser: true,View on GitHub (pinned to 49907e53dc)
Solutions
- Omit click-button and just read the returned Text field — the command already returns the full assistant message, so DOM copy is usually unnecessary.
- Hover/focus the last assistant message before clicking (e.g. move mouse to the turn) so the Copy button renders.
- Wait until the response finishes streaming, then retry.
- Update the SVG name ('Copy') if the Kimi UI changed the icon.
Example fix
// before
await cli('kimi', 'copy-message', { 'click-button': true });
// after
const out = await cli('kimi', 'copy-message'); // no DOM click needed
const text = out.find(r => r.Field === 'Text').Value; Defensive patterns
Strategy: fallback
Type guard
function clickOk(res) { return !!res && res.ok === true; } Try / catch
try {
return await cli('kimi', 'copy-message', { 'click-button': true });
} catch (e) {
if (/Copy button not visible/i.test(e.message)) {
// DOM copy unavailable; use returned text instead
return await cli('kimi', 'copy-message');
}
throw e;
} Prevention
- Prefer the command's returned Text over DOM clipboard clicking.
- Avoid click-button in headless sessions where hover UI doesn't render.
- Wait for streaming to complete before requesting the copy action.
- Re-verify the Copy icon name when Kimi updates its UI.
When it happens
Trigger: Copy button only renders on hover/focus of the assistant message; kwargs['click-button'] is truthy but no response is hovered; Kimi renamed the Copy SVG icon or moved it behind an overflow menu.
Common situations: Headless automation where hover-dependent buttons never appear; Kimi UI updates relocating the copy action; calling click-button on a still-streaming response whose action bar hasn't rendered.
Related errors
- composer type failed
- Send button click failed
- Refresh button not visible
- No messages found in /chat/${id}.
- No chat turns found on current page.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/2d8dac5a59ce2fe7.
Report an issue: GitHub.