jackwener/OpenCLI · error · ArgumentError

shot URL must use dribbble.com

Error message

shot URL must use dribbble.com

What it means

After a shot value parses as a URL, requireShotTarget checks that the hostname is dribbble.com or a subdomain of it. This ArgumentError is thrown when a valid URL points at a different host, because the library only scrapes dribbble.com shot pages.

Source

Thrown at clis/dribbble/utils.js:60

    if (!/^[A-Za-z0-9_-]{1,100}$/.test(designer)) {
        throw new ArgumentError('designer must be a Dribbble username or profile slug');
    }
    return designer;
}

export function requireShotTarget(value) {
    const target = String(value ?? '').trim();
    if (!target) throw new ArgumentError('shot is required (numeric id or dribbble.com/shots URL)');
    if (/^\d+$/.test(target)) return target;

    let url;
    try {
        url = new URL(target);
    } catch {
        throw new ArgumentError('shot must be a numeric id or dribbble.com/shots URL');
    }
    if (!/(^|\.)dribbble\.com$/i.test(url.hostname)) {
        throw new ArgumentError('shot URL must use dribbble.com');
    }
    const match = url.pathname.match(/^\/shots\/(\d+)(?:-|\/|$)/);
    if (!match) throw new ArgumentError('shot URL must match dribbble.com/shots/<id>');
    return match[1];
}

export function requireRows(payload, command) {
    if (!payload || typeof payload !== 'object') {
        throw new CommandExecutionError(`${command} returned an unreadable browser payload`);
    }
    if (payload.empty) {
        throw new EmptyResultError(command, payload.reason || `${command} returned no results`);
    }
    if (!payload.ok) {
        const reason = payload.reason ? `: ${payload.reason}` : '';
        throw new CommandExecutionError(`${command} selector drift${reason}`);
    }
    if (!Array.isArray(payload.rows)) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use the canonical https://dribbble.com/shots/<id> URL.
  2. Extract the numeric id from wherever the link came from and pass the id instead of the URL.
  3. Check for typos in the hostname and ensure redirects are resolved to dribbble.com before passing the URL.

Example fix

// before
cli.shot({ shot: 'https://www.behance.net/gallery/123456/Shot' })

// after
cli.shot({ shot: 'https://dribbble.com/shots/123456' }); // or just 123456
Defensive patterns

Strategy: validation

Validate before calling

const url = new URL(shot);
if (!/(^|\.)dribbble\.com$/i.test(url.hostname)) {
  throw new Error(`shot URL must point at dribbble.com, got ${url.hostname}`);
}

Type guard

function isDribbbleUrl(v) {
  try { return /(^|\.)dribbble\.com$/i.test(new URL(String(v)).hostname); } catch { return false; }
}

Try / catch

try {
  const result = command({ shot });
} catch (e) {
  if (e instanceof ArgumentError && /shot URL must use dribbble\.com/.test(e.message)) {
    console.error('Only dribbble.com shot URLs are supported; extract the id and pass that instead');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing URLs from other sites (e.g. 'https://www.behance.net/gallery/123', 'https://example.com/shots/123') or mirror/proxied hosts that are not dribbble.com or *.dribbble.com.

Common situations: Mixing up shot links from other design sites stored in the same dataset, using a shortened link (bit.ly etc.) that resolves to a non-dribbble host string, or a typo like 'dribbble.org'.

Related errors


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