{"record":{"id":"7e5452dcac732c22","repo":"jackwener/OpenCLI","slug":"result-reason-failed-to-name-conversatio","errorCode":null,"errorMessage":"${result?.reason || `Failed to ${name} conversation.`}${detail}","messagePattern":"(.+?) conversation\\.`\\}(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/grok/pin.js","lineNumber":49,"sourceCode":"        func: async (page, kwargs) => {\n            const id = parseGrokSessionId(kwargs.id);\n            await ensureOnGrok(page);\n            if (!(await isLoggedIn(page))) throw authRequired();\n\n            const expectedState = name === 'pin' ? 'pinned' : 'unpinned';\n            const before = await readConversationMenuLabels(page, id);\n            if (!before.ok) {\n                const detail = before.detail ? ` ${before.detail}` : '';\n                throw new CommandExecutionError(`${before.reason || `Failed to inspect ${name} state.`}${detail}`, SESSION_HINT);\n            }\n            if (getPinStateFromMenuLabels(before.labels) === expectedState) {\n                return [{ status: `already-${expectedState}`, id }];\n            }\n\n            const result = await clickConversationMenuItem(page, id, accessLabels);\n            if (!result || !result.ok) {\n                const detail = result?.detail ? ` ${result.detail}` : '';\n                throw new CommandExecutionError(`${result?.reason || `Failed to ${name} conversation.`}${detail}`, SESSION_HINT);\n            }\n            const verified = await waitForConversationPinState(page, id, expectedState);\n            if (!verified.ok) {\n                const labels = verified.labels?.length ? ` labels=${JSON.stringify(verified.labels)}` : '';\n                throw new CommandExecutionError(\n                    `${name} menu item was clicked, but the conversation did not verify as ${expectedState}.${labels}`,\n                    SESSION_HINT,\n                );\n            }\n            return [{ status: name === 'pin' ? 'pinned' : 'unpinned', id }];\n        },\n    });\n}\n\n// Grok's context menu shows EITHER \"置顶\" OR \"取消置顶\" depending on the\n// current pin state, never both. We register two commands that bind to\n// the matching label so callers can use whichever they want.\ndefineToggle('pin', ['置顶', 'pin']);","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/grok/pin.js#L31-L67","documentation":"After reading the menu, defineToggle clicks the pin/unpin menu item via clickConversationMenuItem; if the click result is missing or reports ok:false, this CommandExecutionError is thrown with result.reason (or a 'Failed to pin/unpin conversation' default) plus detail. It means the menu item itself could not be clicked or the click action failed.","triggerScenarios":"clickConversationMenuItem returns {ok:false} or null because the menu closed mid-click, the item selector missed, the element was intercepted by an overlay, or the item is disabled.","commonSituations":"Animated menus that close before the click lands, Grok UI rename of the 'Pin'/'Unpin' items, an interfering notification toast, or the conversation list re-rendering during the click.","solutions":["Re-run the command — transient overlay/animation races usually succeed on retry.","Check the reason/detail in the message for the failing click step.","Reload the grok.com tab and ensure no dialogs are open, then retry.","Update the library if Grok's menu markup changed."],"exampleFix":"// before\ncli unpin --id <id>  // menu closed before click\n// after\n// keep the tab focused and retry:\ncli unpin --id <id>","handlingStrategy":"retry","validationCode":"// Ensure no overlay blocks clicks before toggling:\nconst overlay = await page.$('.modal, [role=dialog]');\nif (overlay) throw new Error('close open dialogs before pin/unpin operations');","typeGuard":null,"tryCatchPattern":"async function pinWithRetry(id, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await cli.pin({ id }); }\n    catch (e) {\n      if (e instanceof CommandExecutionError && /Failed to pin conversation/.test(e.message) && i < attempts - 1) {\n        await new Promise(r => setTimeout(r, 1000 * (i + 1)));\n        continue;\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Retry menu clicks — animation and re-render races are transient.","Keep the tab focused so hover menus open reliably.","Dismiss toasts/dialogs that can intercept clicks.","Update the library after Grok UI changes."],"tags":["browser-automation","click","ui-selector"],"backgroundTag":"browser-automation-selector-failure","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}