jackwener/OpenCLI · error · ArgumentError
${e.message} (rethrown as ArgumentError)
Error message
${e.message} (rethrown as ArgumentError) What it means
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.
Source
Thrown at clis/slock/thread-follow.js:29
// thread-unfollow/-done/-undone commands.
cli({
site: SLOCK_SITE,
name: 'thread-follow',
access: 'write',
description: 'Follow the thread on a parent message (POST /channels/threads/follow)',
domain: SLOCK_DOMAIN,
strategy: Strategy.COOKIE,
browser: true,
siteSession: 'persistent',
args: [
{ name: 'parentMessageId', positional: true, required: true, help: 'Full parent messageId UUID (short ids rejected)' },
{ name: 'server', help: 'Override active server' },
],
columns: ['parentMessageId', 'threadChannelId', 'result'],
func: async (page, kwargs) => {
let id;
try { id = assertMessageIdShape(String(kwargs.parentMessageId ?? '')); }
catch (e) { throw new ArgumentError(e.message); }
await page.goto(SLOCK_HOME_URL);
const snippet = buildFetchSnippet({
method: 'POST',
path: '/channels/threads/follow',
body: { parentMessageId: id },
serverScoped: true,
serverIdOverride: kwargs.server,
});
const result = await page.evaluate(`(async () => { ${snippet} })()`);
const data = dispatchEvaluateResult(result);
const threadChannelId = data?.threadChannelId ?? data?.channelId ?? data?.id;
if (!threadChannelId) {
throw new CommandExecutionError(`Slock thread-follow succeeded without returning a thread channel id for parent message ${id}.`);
}
return [{ parentMessageId: id, threadChannelId, result: 'followed' }];
},
});
View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before await cli.run(['thread-follow', '--parent-message-id', threadChannelId]); // wrong id kind // after await cli.run(['thread-follow', '--parent-message-id', message.parentMessageId]);
Defensive patterns
Strategy: validation
Validate before calling
const id = String(kwargs.parentMessageId ?? '').trim();
if (!id) throw new Error('parentMessageId is required'); Type guard
function looksLikeMessageId(s) { return typeof s === 'string' && /^[A-Za-z0-9_-]{6,}$/.test(s.trim()); } Try / catch
try {
await cli.run(['thread-follow', '--parent-message-id', id]);
} catch (e) {
if (String(e.message).includes('rethrown as ArgumentError')) {
console.error(`"${id}" is not a valid parent message id — fetch one via message-read`);
} else throw e;
} Prevention
- Pass the parent message id, never a channel or thread id
- Trim/normalize ids in wrappers
- Source ids from message-read/list output
When it happens
Trigger: 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).
Common situations: Passing a threadChannelId where a parent message id is required; unset variables in shell scripts; ids mangled by quoting/interpolation in wrappers.
Related errors
- ${e.message} (rethrown as ArgumentError)
- <train-no> "${trainNo}" does not look like a 12306 internal
- --from station must not be empty
- --to station must not be empty
- --seat-types must contain only 12306 seat letters/digits (A-
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0f71f62902957f60.
Report an issue: GitHub.