{"record":{"id":"7f6386b8bdeda3f9","repo":"jackwener/OpenCLI","slug":"must-be-a-conversation-id-app-id-url-or-sideb","errorCode":null,"errorMessage":"must be a conversation id, /app/<id> URL, or sidebar title","messagePattern":"must be a conversation id, /app/<id> URL, or sidebar title","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/gemini/detail.js","lineNumber":24,"sourceCode":"    ensureGeminiPage,\n    getGeminiConversationList,\n    getGeminiVisibleTurns,\n    resolveGeminiConversationForQuery,\n} from './utils.js';\nimport { extractGeminiId } from './history.js';\n\n/**\n * Resolve the caller-supplied `<id>` argument into an absolute\n * conversation URL. Accepts:\n *   1. A bare conversation id (`b8368a89d4242e5f`)\n *   2. A relative `/app/<id>` path\n *   3. A full `https://gemini.google.com/app/<id>` URL\n *   4. A sidebar title — looked up exactly first, then by substring\n */\nasync function resolveTargetUrl(page, query) {\n    const raw = String(query || '').trim();\n    if (!raw) {\n        throw new ArgumentError('id', 'must be a conversation id, /app/<id> URL, or sidebar title');\n    }\n\n    // Unambiguously id-shaped inputs (URL, /app/<id> path, or 16-hex bare id)\n    // skip the sidebar lookup. Generic alphanumeric strings always go through\n    // title-matching first so a chat called \"Empire study\" doesn't get treated\n    // as the literal conversation id \"Empire study\".\n    const directId = extractGeminiId(raw);\n    const looksLikeId =\n        raw.startsWith('http') ||\n        raw.startsWith('/app/') ||\n        /^[a-f0-9]{16,}$/i.test(raw);\n    if (directId && looksLikeId) {\n        return `${GEMINI_APP_URL}/${directId}`;\n    }\n\n    const conversations = await getGeminiConversationList(page);\n    const match = resolveGeminiConversationForQuery(conversations, raw, 'contains');\n    if (!match || !match.Url) {","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/detail.js#L6-L42","documentation":"resolveTargetUrl in gemini detail throws ArgumentError with the message 'must be a conversation id, /app/<id> URL, or sidebar title' when the query argument is empty or only whitespace after trimming. It tells the caller which three forms of the --id argument are accepted. The error is raised before any page navigation or sidebar lookup happens.","triggerScenarios":"Calling `opencli gemini detail` without --id; passing an empty string --id ''; passing whitespace '   '; passing null/undefined programmatically into the target command's kwargs.id.","commonSituations":"A script variable holding the conversation id is empty because a previous history lookup returned nothing; quoting mistakes dropping the value (--id \"\"); copy-paste that grabbed only whitespace; forgetting the flag on first use.","solutions":["Provide a valid --id value: a bare conversation id, a full https://gemini.google.com/app/<id> URL, an /app/<id> path, or a sidebar title","If the id comes from another command, capture the output of `opencli gemini history` first and use its Id or Url column","Trim the value in scripts and skip the call if empty rather than invoking with a blank argument","Check shell quoting so the argument actually reaches the command"],"exampleFix":"// before\nconst id = convo?.Id ?? '';\nawait run(['gemini', 'detail', '--id', id]);\n// after\nconst id = convo?.Id ?? '';\nif (!id.trim()) throw new Error('No conversation id available; run gemini history first');\nawait run(['gemini', 'detail', '--id', id]);","handlingStrategy":"validation","validationCode":"const id = (kwargs?.id ?? '').trim();\nif (!id) throw new Error('gemini detail requires a non-empty --id (id, /app/<id> URL, or sidebar title)');","typeGuard":"function hasTarget(q){ return typeof q === 'string' && q.trim().length > 0; }","tryCatchPattern":"try {\n  await run(['gemini','detail','--id', id]);\n} catch (e) {\n  if (String(e.message).includes('must be a conversation id')) {\n    console.error('Provide --id as a conversation id, /app/<id> URL, or sidebar title.');\n  } else throw e;\n}","preventionTips":["Resolve ids from `opencli gemini history` output before calling detail","Trim and check non-empty before invoking","Avoid passing possibly-empty variables; use shell defaults like ID=\"${ID:?missing id}\""],"tags":["argument-error","validation","cli","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}