{"record":{"id":"0f71f62902957f60","repo":"jackwener/OpenCLI","slug":"e-message-rethrown-as-argumenterror-0f71f6","errorCode":null,"errorMessage":"${e.message} (rethrown as ArgumentError)","messagePattern":"(.+?) \\(rethrown as ArgumentError\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/slock/thread-follow.js","lineNumber":29,"sourceCode":"// thread-unfollow/-done/-undone commands.\ncli({\n  site: SLOCK_SITE,\n  name: 'thread-follow',\n  access: 'write',\n  description: 'Follow the thread on a parent message (POST /channels/threads/follow)',\n  domain: SLOCK_DOMAIN,\n  strategy: Strategy.COOKIE,\n  browser: true,\n  siteSession: 'persistent',\n  args: [\n    { name: 'parentMessageId', positional: true, required: true, help: 'Full parent messageId UUID (short ids rejected)' },\n    { name: 'server', help: 'Override active server' },\n  ],\n  columns: ['parentMessageId', 'threadChannelId', 'result'],\n  func: async (page, kwargs) => {\n    let id;\n    try { id = assertMessageIdShape(String(kwargs.parentMessageId ?? '')); }\n    catch (e) { throw new ArgumentError(e.message); }\n    await page.goto(SLOCK_HOME_URL);\n    const snippet = buildFetchSnippet({\n      method: 'POST',\n      path: '/channels/threads/follow',\n      body: { parentMessageId: id },\n      serverScoped: true,\n      serverIdOverride: kwargs.server,\n    });\n    const result = await page.evaluate(`(async () => { ${snippet} })()`);\n    const data = dispatchEvaluateResult(result);\n    const threadChannelId = data?.threadChannelId ?? data?.channelId ?? data?.id;\n    if (!threadChannelId) {\n      throw new CommandExecutionError(`Slock thread-follow succeeded without returning a thread channel id for parent message ${id}.`);\n    }\n    return [{ parentMessageId: id, threadChannelId, result: 'followed' }];\n  },\n});\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/slock/thread-follow.js#L11-L47","documentation":"The thread-follow command validates the parentMessageId with assertMessageIdShape and rethrows failures as an ArgumentError with a \"(rethrown as ArgumentError)\" suffix. This separates input-shape errors from network/API errors so callers can react to bad input deterministically.","triggerScenarios":"Running `slock thread-follow` with a parentMessageId that is empty, malformed, or not the id format assertMessageIdShape expects (e.g. a channel id or thread id passed instead of the parent message id).","commonSituations":"Passing a threadChannelId where a parent message id is required; unset variables in shell scripts; ids mangled by quoting/interpolation in wrappers.","solutions":["Take parentMessageId from the message-read/list output, not from a thread or channel id.","Echo the id before invoking and validate it matches the expected id shape.","Trim whitespace and strip stray quotes before passing.","Wrap the call in a try/catch for ArgumentError and print corrected usage."],"exampleFix":"// before\nawait cli.run(['thread-follow', '--parent-message-id', threadChannelId]); // wrong id kind\n// after\nawait cli.run(['thread-follow', '--parent-message-id', message.parentMessageId]);","handlingStrategy":"validation","validationCode":"const id = String(kwargs.parentMessageId ?? '').trim();\nif (!id) throw new Error('parentMessageId is required');","typeGuard":"function looksLikeMessageId(s) { return typeof s === 'string' && /^[A-Za-z0-9_-]{6,}$/.test(s.trim()); }","tryCatchPattern":"try {\n  await cli.run(['thread-follow', '--parent-message-id', id]);\n} catch (e) {\n  if (String(e.message).includes('rethrown as ArgumentError')) {\n    console.error(`\"${id}\" is not a valid parent message id — fetch one via message-read`);\n  } else throw e;\n}","preventionTips":["Pass the parent message id, never a channel or thread id","Trim/normalize ids in wrappers","Source ids from message-read/list output"],"tags":["argument-validation","input-shape","cli"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}