jackwener/OpenCLI · error · ArgumentError

attachmentId "${id}" is not a UUID

Error message

attachmentId "${id}" is not a UUID

What it means

An ArgumentError thrown during argument validation of the slock attachment-download CLI command: the provided attachmentId does not match UUID_RE, so it cannot be a valid Slock attachment identifier. The download flow (signed URL resolution, CDN fetch) is aborted before any network calls.

Source

Thrown at clis/slock/attachment-download.js:42

cli({
  site: SLOCK_SITE,
  name: 'attachment-download',
  access: 'read',
  description: 'Download an attachment to a local file. Resolves a signed CDN URL in the page, then fetches bytes node-side (no CORS).',
  domain: SLOCK_DOMAIN,
  strategy: Strategy.COOKIE,
  browser: true,
  siteSession: 'persistent',
  args: [
    { name: 'attachmentId', positional: true, required: true, help: 'Attachment UUID' },
    { name: 'out', help: 'Local path to write to. Defaults to ./<attachmentId>.bin' },
    { name: 'server', help: 'Override active server slug' },
  ],
  columns: ['attachmentId', 'out', 'sizeBytes'],
  func: async (page, kwargs) => {
    const id = String(kwargs.attachmentId ?? '').trim();
    if (!UUID_RE.test(id)) throw new ArgumentError(`attachmentId "${id}" is not a UUID`);
    const out = path.resolve(String(kwargs.out ?? `./${id}.bin`));

    // Step 1 — in-page, resolve the signed URL with the user's Slock session.
    await page.goto(SLOCK_HOME_URL);
    const snippet = buildFetchSnippet({
      method: 'GET',
      path: `/attachments/${encodeURIComponent(id)}/url`,
      serverScoped: true,
      serverIdOverride: kwargs.server,
    });
    const result = await page.evaluate(`(async () => { ${snippet} })()`);
    const rows = dispatchEvaluateResult(result);
    const data = Array.isArray(rows) ? rows[0] : rows;
    const url = data?.url;
    if (!url) throw new CommandExecutionError(`no signed url returned for attachment ${id}`);

    // Step 2 — Node side, fetch the bytes from the signed CDN URL. No auth
    // header (URL is pre-signed); no Origin (Node fetch has none) so CORS

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-copy the full UUID of the attachment (8-4-4-4-12 hex format) and pass it again
  2. Check you are using the attachment's UUID, not its numeric ID or filename
  3. Trim surrounding quotes/whitespace from the argument in your shell invocation
  4. Run the list command (same CLI) to get valid attachmentIds with their columns

Example fix

// before
node cli attachment-download --attachmentId 12345
// after
node cli attachment-download --attachmentId 550e8400-e29b-41d4-a716-446655440000
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;
if (!UUID_RE.test(String(id ?? '').trim())) {
  throw new Error('attachmentId must be a canonical UUID');
}

Type guard

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

Prevention

When it happens

Trigger: Passing kwargs.attachmentId that is empty, whitespace-only, a numeric database ID, a truncated/copied-partial UUID, or a value with surrounding characters instead of a canonical UUID string.

Common situations: Copying only part of the attachment ID from a UI URL; passing an integer row ID from a database export; forgetting the argument entirely (empty string after trim); pasting an ID wrapped in quotes or with trailing whitespace/newline.

Related errors


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