{"record":{"id":"84dc2f47d25501e9","repo":"jackwener/OpenCLI","slug":"id-not-a-valid-grok-url-got-input","errorCode":null,"errorMessage":"id not a valid Grok URL (got \"${input}\")","messagePattern":"id not a valid Grok URL \\(got \"(.+?)\"\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/grok/utils.js","lineNumber":45,"sourceCode":"    const normalized = String(value).trim().toLowerCase();\n    return normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on';\n}\n\n// UUID v4-shape: 8-4-4-4-12 hex with dashes (the format Grok uses for /c/<id>)\nconst GROK_SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function parseGrokSessionId(input) {\n    const raw = String(input ?? '').trim();\n    if (!raw) {\n        throw new ArgumentError('id', 'must be a non-empty session ID or grok.com chat URL');\n    }\n    let candidate = raw;\n    if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(raw)) {\n        let parsed;\n        try {\n            parsed = new URL(raw);\n        } catch {\n            throw new ArgumentError('id', `not a valid Grok URL (got \"${input}\")`);\n        }\n        const host = parsed.hostname.toLowerCase();\n        const pathMatch = parsed.pathname.match(\n            /^\\/c\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\/?$/i,\n        );\n        if (parsed.protocol !== 'https:' || (host !== 'grok.com' && !host.endsWith('.grok.com')) || !pathMatch) {\n            throw new ArgumentError(\n                'id',\n                `not a valid Grok conversation URL (got \"${input}\"); expected https://grok.com/c/<id>`,\n            );\n        }\n        candidate = pathMatch[1];\n    }\n    if (!GROK_SESSION_ID_RE.test(candidate)) {\n        throw new ArgumentError(\n            'id',\n            `not a valid Grok session ID (got \"${input}\"); expected a UUID like \"7c4197f2-10a1-4ebb-a84a-fea89f4f1d06\" or a full https://grok.com/c/<id> URL`,\n        );","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/grok/utils.js#L27-L63","documentation":"parseGrokSessionId accepts either a bare UUID session id or a full https://grok.com/c/<uuid> URL. When the input looks like a URL (matches a scheme prefix like https:// or http://) but cannot be parsed by the URL constructor at all, the function throws this ArgumentError naming the 'id' argument. This is the earliest of three validation failures in the same parser.","triggerScenarios":"Calling any grok CLI command that takes an id (delete id, detail sessionId, pin) with a malformed URL string such as 'https://grok.com/c/%zz' with invalid percent-encoding, or a truncated scheme like 'https:/grok.com/c/...' that makes new URL() throw.","commonSituations":"Pasting a URL from the browser and accidentally dropping a slash or adding shell-escaped characters; template string interpolation producing 'http://\\example'; shell mangling of '#' or '%' characters in the URL.","solutions":["Check the id string: if it is a full URL, ensure it is a well-formed absolute URL that new URL() can parse (valid scheme like https://, no stray characters).","Prefer passing just the UUID session id (e.g. 7c4197f2-10a1-4ebb-a84a-fea89f4f1d06) instead of a URL — that path skips URL parsing entirely.","Quote the URL in your shell so special characters are not mangled.","Validate with a try { new URL(input) } before calling."],"exampleFix":"// before\nnode cli.js grok delete 'https:/grok.com/c/7c4197f2-10a1-4ebb-a84a-fea89f4f1d06'\n// after\nnode cli.js grok delete 'https://grok.com/c/7c4197f2-10a1-4ebb-a84a-fea89f4f1d06'\n// or simply\nnode cli.js grok delete 7c4197f2-10a1-4ebb-a84a-fea89f4f1d06","handlingStrategy":"validation","validationCode":"function looksLikeUrl(s) { return /^[a-z][a-z0-9+.-]*:\\/\\//i.test(s); }\nfunction isParseableUrl(s) { try { new URL(s); return true; } catch { return false; } }\nif (looksLikeUrl(id) && !isParseableUrl(id)) throw new Error(`malformed URL: ${id}`);","typeGuard":"function isUsableGrokId(input) {\n  if (!/^[a-z][a-z0-9+.-]*:\\/\\//i.test(input)) return /^[0-9a-f-]{36}$/i.test(input);\n  try { new URL(input); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const id = parseGrokSessionId(raw);\n} catch (e) {\n  if (e instanceof ArgumentError && /not a valid Grok URL/.test(e.message)) {\n    console.error(`Fix the id URL syntax: ${raw}`);\n  } else throw e;\n}","preventionTips":["Pass the bare UUID instead of a URL whenever possible","Quote URLs in shell to avoid character mangling","Validate with new URL(input) before invoking","Trim the input of stray whitespace/newlines"],"tags":["argument-validation","url-parsing","cli"],"backgroundTag":"invalid-url-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}