{"record":{"id":"1a9690a67cb57816","repo":"jackwener/OpenCLI","slug":"before-reason-failed-to-inspect-name-stat","errorCode":null,"errorMessage":"${before.reason || `Failed to inspect ${name} state.`}${detail}","messagePattern":"(.+?) state\\.`\\}(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/grok/pin.js","lineNumber":40,"sourceCode":"        description: `${name === 'pin' ? 'Pin' : 'Unpin'} a Grok conversation by ID`,\n        domain: GROK_DOMAIN,\n        strategy: Strategy.COOKIE,\n        browser: true,\n        siteSession: 'persistent',\n        args: [\n            { name: 'id', positional: true, type: 'string', required: true, help: 'Conversation UUID or grok.com/c/<uuid> URL' },\n        ],\n        columns: ['status', 'id'],\n        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            }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/grok/pin.js#L22-L58","documentation":"defineToggle's pin/unpin flow first reads the conversation's context-menu labels via readConversationMenuLabels; if that inspection fails (before.ok false), this CommandExecutionError is thrown combining before.reason and optional detail. The library cannot even determine the conversation's current pin state, so it aborts rather than clicking blindly.","triggerScenarios":"Calling the pin or unpin command with a conversation id whose menu cannot be opened/read — the conversation no longer exists, the menu DOM changed, or the page is in a logged-out state (auth is checked just before).","commonSituations":"Stale or mistyped conversation id for a deleted chat, Grok UI update renaming menu items, or expired session after the initial isLoggedIn check raced with a logout.","solutions":["Verify the conversation id exists — open it in the grok.com tab.","Confirm the browser tab is still logged into grok.com and retry.","Reload the page to rebuild DOM state, then re-run the command.","Update the library if menu selectors changed in a Grok UI update."],"exampleFix":"// before\ncli pin --id 00000000-0000-4000-8000-000000000000  // deleted conversation\n// after\ncli pin --id <id-of-an-existing-conversation>","handlingStrategy":"validation","validationCode":"const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nif (!UUID_RE.test(id)) throw new Error(`invalid conversation id: ${id}`);\n// Also confirm the conversation exists before toggling:\nconst exists = await page.goto(`https://grok.com/c/${id}`, { waitUntil: 'domcontentloaded' });\nif (!exists || page.url().includes('404')) throw new Error(`conversation ${id} not found`);","typeGuard":"function isGrokConversationId(v) {\n  return typeof v === 'string' &&\n    /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v.trim());\n}","tryCatchPattern":"try {\n  await cli.pin({ id });\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.startsWith('Failed to inspect')) {\n    console.error(`Cannot read pin state for ${id} — verify it exists and the tab is logged in.`);\n  } else throw e;\n}","preventionTips":["Validate the conversation id (UUID v4 shape) before invoking pin/unpin.","Confirm the conversation still exists — deleted chats fail inspection.","Ensure the browser tab is logged in before toggle operations.","Reload the tab periodically to keep DOM state fresh."],"tags":["browser-automation","session","ui-selector"],"backgroundTag":"browser-automation-selector-failure","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}