jackwener/OpenCLI · error · ArgumentError

--attach expects attachmentId UUIDs; "${aid}" is not a UUID

Error message

--attach expects attachmentId UUIDs; "${aid}" is not a UUID

What it means

message-send.js parses `--attach` as a comma-separated list of attachmentId UUIDs and validates each against UUID_RE. Any entry that isn't a valid UUID throws this ArgumentError naming the bad entry.

Source

Thrown at clis/slock/message-send.js:35

  siteSession: 'persistent',
  args: [
    { name: 'target', positional: true, required: true, help: '"#channel", "#channel:msgIdOrShort", "dm:@name", "dm:<uuid>", or channel UUID' },
    { name: 'content', positional: true, required: true, help: 'Message body (sent verbatim, no marker)' },
    { name: 'dry-run', type: 'bool', default: false, help: 'Print the planned payload without sending' },
    { name: 'as-task', type: 'bool', default: false, help: 'Create the message as a task (asTask)' },
    { name: 'attach', help: 'Comma-separated attachmentId UUIDs (upload separately first)' },
    { name: 'server', help: 'Override active server (slug or id)' },
  ],
  columns: ['target', 'channelId', 'content', 'result', 'messageId'],
  func: async (page, kwargs) => {
    const target = String(kwargs.target ?? '').trim();
    if (!target) throw new ArgumentError('target required');
    const content = String(kwargs.content ?? '');
    const asTask = !!kwargs['as-task'];
    const attachmentIds = String(kwargs.attach ?? '')
      .split(',').map((s) => s.trim()).filter(Boolean);
    for (const aid of attachmentIds) {
      if (!UUID_RE.test(aid)) throw new ArgumentError(`--attach expects attachmentId UUIDs; "${aid}" is not a UUID`);
    }
    let cls;
    try { cls = classifyTarget(target); }
    catch (e) { throw new ArgumentError(e.message); }

    const extra = { asTask, attachmentIds };

    if (kwargs['dry-run']) {
      return [{
        target, channelId: '(not resolved in dry-run)', content,
        result: asTask ? 'dry-run (asTask)' : 'dry-run', messageId: null,
      }];
    }

    await page.goto(SLOCK_HOME_URL);
    const snippet = buildSendSnippet(target, content, cls, kwargs.server, extra);
    const result = await page.evaluate(`(async () => { ${snippet} })()`);
    const rows = dispatchEvaluateResult(result);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Upload the file first (upload command) and use the returned attachmentId UUID.
  2. Fix typos/truncation in the UUID (must match the standard UUID format).
  3. Comma-separate multiple ids without extra tokens: `--attach <uuid1>,<uuid2>`.

Example fix

// before
--attach ./report.pdf
// after
--attach 9b2f0a1c-3d4e-4f5a-8b9c-0d1e2f3a4b5c
Defensive patterns

Strategy: validation

Validate before calling

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
for (const aid of String(kwargs.attach ?? '').split(',').map(s => s.trim()).filter(Boolean)) {
  if (!UUID_RE.test(aid)) throw new Error(`--attach needs attachmentId UUIDs; "${aid}" is not a UUID`);
}

Type guard

const isUuid = (v) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(String(v));

Try / catch

try { await sendMessage(page, kwargs); } catch (e) { if (String(e.message).includes('--attach expects attachmentId UUIDs')) { console.error('Upload files first and pass returned attachmentId UUIDs'); } else throw e; }

Prevention

When it happens

Trigger: Passing `--attach` values that are file paths, filenames, short ids, upload-returned names instead of UUIDs, or a list with stray whitespace-adjacent garbage tokens.

Common situations: Passing local file paths to --attach instead of uploading first and using returned attachmentIds; copying a truncated UUID; comma+space splitting leaving empty or malformed tokens.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/b98116ee3d0622b7. Report an issue: GitHub.