{"record":{"id":"dbadf600e5e44f18","repo":"jackwener/OpenCLI","slug":"threadchannelid-must-be-a-full-uuid-got-id","errorCode":null,"errorMessage":"threadChannelId must be a full UUID (got \"${id}\"). Get it from thread-list or message-read's threadChannelId column.","messagePattern":"threadChannelId must be a full UUID \\(got \"(.+?)\"\\)\\. Get it from thread-list or message-read's threadChannelId column\\.","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/slock/thread-state.js","lineNumber":30,"sourceCode":"export function makeThreadStateCommand({ name, verb, resultLabel, description }) {\n  cli({\n    site: SLOCK_SITE,\n    name,\n    access: 'write',\n    description,\n    domain: SLOCK_DOMAIN,\n    strategy: Strategy.COOKIE,\n    browser: true,\n    siteSession: 'persistent',\n    args: [\n      { name: 'threadChannelId', positional: true, required: true, help: 'Thread channel UUID (from thread-list / message-read)' },\n      { name: 'server', help: 'Override active server' },\n    ],\n    columns: ['threadChannelId', 'result'],\n    func: async (page, kwargs) => {\n      const id = String(kwargs.threadChannelId ?? '').trim();\n      if (!UUID_RE.test(id)) {\n        throw new ArgumentError(`threadChannelId must be a full UUID (got \"${id}\"). Get it from thread-list or message-read's threadChannelId column.`);\n      }\n      await page.goto(SLOCK_HOME_URL);\n      const snippet = buildFetchSnippet({\n        method: 'POST',\n        path: `/channels/threads/${verb}`,\n        body: { threadChannelId: id },\n        serverScoped: true,\n        serverIdOverride: kwargs.server,\n      });\n      const result = await page.evaluate(`(async () => { ${snippet} })()`);\n      dispatchEvaluateResult(result);\n      return [{ threadChannelId: id, result: resultLabel }];\n    },\n  });\n}\n","sourceCodeStart":12,"sourceCodeEnd":46,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/slock/thread-state.js#L12-L46","documentation":"thread-state (built via makeThreadStateCommand for read/mark verbs) requires threadChannelId to be a full UUID and validates it with UUID_RE before issuing any request; a non-UUID input throws this ArgumentError immediately with a pointer to where a valid id can be obtained (thread-list or message-read).","triggerScenarios":"Passing a short/partial id, a human-readable thread name, a parent message id, or a value with surrounding whitespace/quotes to `thread-state --thread-channel-id`.","commonSituations":"Copy/paste truncated ids from logs; confusing threadChannelId with parentMessageId; interpolating ids into shell commands where quotes become part of the value.","solutions":["Get the exact threadChannelId from the `thread-list` command's threadChannelId column.","Or take it from message-read's threadChannelId column as the error suggests.","Trim the input; ensure no stray quotes or partial (non-UUID) ids are passed.","Validate with a UUID regex in your wrapper before invoking."],"exampleFix":"// before\nawait cli.run(['thread-state', '--thread-channel-id', msg.parentMessageId]);\n// after\nif (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(msg.threadChannelId))\n  throw new Error('need a full UUID threadChannelId');\nawait cli.run(['thread-state', '--thread-channel-id', msg.threadChannelId]);","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;\nconst id = String(threadChannelId ?? '').trim();\nif (!UUID_RE.test(id)) throw new Error(`threadChannelId must be a full UUID, got: ${id}`);","typeGuard":"function isUuid(s) { return typeof s === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s.trim()); }","tryCatchPattern":"try {\n  await cli.run(['thread-state', '--thread-channel-id', id]);\n} catch (e) {\n  if (String(e.message).includes('must be a full UUID')) {\n    const threads = await cli.run(['thread-list']);\n    console.error('valid ids:', threads.map(t => t.threadChannelId));\n  } else throw e;\n}","preventionTips":["Always source threadChannelId from thread-list or message-read","Trim inputs to remove stray quotes/whitespace","Validate UUID shape in scripts before invoking"],"tags":["argument-validation","uuid","input-shape"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}