jackwener/OpenCLI · error · ArgumentError

Pinterest usernames have no "@": "${raw}"

Error message

Pinterest usernames have no "@": "${raw}"

What it means

Pinterest usernames do not use '@' prefixes (unlike Twitter/Instagram handles). parseUsername detects a leading '@' after normalization and throws this ArgumentError telling you to drop it. This prevents sending '@janedoe' to the API where it would fail as an unknown user.

Source

Thrown at clis/pinterest/utils.js:112

  let value = String(raw ?? '').trim();
  if (!value) throw new ArgumentError('username is required', 'Pass a Pinterest username or profile URL, e.g. janedoe');
  if (/^https?:\/\//i.test(value)) {
    try {
      value = decodeSegment(new URL(value).pathname.split('/').filter(Boolean)[0] || '');
    } catch {
      throw new ArgumentError(`Invalid profile URL: ${raw}`, 'Use a full profile URL like https://www.pinterest.com/janedoe/');
    }
  }
  value = value.replace(/^\/+|\/+$/g, '');
  if (!value) throw new ArgumentError(`Not a username: "${raw}"`, 'Pass the bare username, e.g. janedoe');
  if (value.includes('/')) {
    throw new ArgumentError(
      `Not a username: "${raw}"`,
      'This looks like a board or pin reference — pass just the username, e.g. janedoe',
    );
  }
  if (value.startsWith('@')) {
    throw new ArgumentError(`Pinterest usernames have no "@": "${raw}"`, 'Drop the @ and use the bare username, e.g. janedoe');
  }
  return value;
}

/** Parse a bare pin id or a /pin/<id>/ URL. */
export function parsePinId(raw) {
  const value = String(raw ?? '').trim();
  if (!value) throw new ArgumentError('pin id is required', 'Pass a pin id or /pin/<id>/ URL, e.g. 1234567890123456');
  if (/^\d+$/.test(value)) return value;
  const match = value.match(/\/pin\/(\d+)/);
  if (match) return match[1];
  throw new ArgumentError(`Not a pin id or pin URL: "${raw}"`, 'Expected a numeric id or a /pin/<id>/ URL, e.g. 1234567890123456');
}

/** Highest-resolution image URL available for a pin. */
export function pickPinImage(images) {
  if (!images || typeof images !== 'object') return '';
  for (const key of ['orig', '736x', '564x', '474x', '236x']) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Remove the '@' and pass the bare username, e.g. janedoe
  2. Normalize in your code: value.replace(/^@+/, '') before calling
  3. Update cross-posted config/templates to store plain usernames
  4. Search your config for '@' prefixes on Pinterest credentials

Example fix

// before
const user = parseUsername('@janedoe');
// after
const user = parseUsername('@janedoe'.replace(/^@+/, '')); // 'janedoe'
Defensive patterns

Strategy: validation

Validate before calling

const cleaned = String(input || '').trim().replace(/^@+/, '');
if (cleaned !== input) console.warn('stripped @ from username');

Type guard

const isHandleFree = (v) => typeof v === 'string' && !v.startsWith('@');

Try / catch

try {
  username = parseUsername(input);
} catch (err) {
  if (err instanceof ArgumentError && err.message.includes('"@"')) {
    username = parseUsername(input.replace(/^@+/, ''));
  } else throw err;
}

Prevention

When it happens

Trigger: Calling parseUsername('@janedoe') or a URL-like '@janedoe/...' — the stripped value starts with '@'.

Common situations: Migrating scripts from a Twitter/Instagram integration that used @handles; users typing the handle as displayed in the Pinterest UI; config copied from another service's docs.

Related errors


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