jackwener/OpenCLI · error · ArgumentError

Invalid board URL: ${trimmed}

Error message

Invalid board URL: ${trimmed}

What it means

tryParseBoardRef accepts a board URL, a username/slug path, or a numeric id. When the input looks like an http(s) URL but cannot be parsed by the URL constructor, this ArgumentError is thrown. It catches malformed URLs early rather than producing a bogus board reference.

Source

Thrown at clis/pinterest/utils.js:74

    return decodeURIComponent(segment);
  } catch {
    return segment;
  }
}

/**
 * Parse a board URL or <username>/<slug> into { username, slug, path }.
 * Returns null for anything else (e.g. a bare board id, which needs an API lookup).
 */
export function tryParseBoardRef(raw) {
  const trimmed = String(raw ?? '').trim();
  if (!trimmed) return null;
  let pathname = trimmed;
  if (/^https?:\/\//i.test(trimmed)) {
    try {
      pathname = new URL(trimmed).pathname;
    } catch {
      throw new ArgumentError(`Invalid board URL: ${trimmed}`, 'Use a full board URL like https://www.pinterest.com/janedoe/my-board/');
    }
  }
  // Pinterest percent-encodes non-ASCII slugs in the URLs it hands out; the API wants them decoded.
  const parts = pathname.split('/').filter(Boolean).map(decodeSegment);
  if (parts.length < 2) return null;
  const [username, slug] = parts;
  if (RESERVED_PATH_ROOTS.has(username.toLowerCase())) {
    throw new ArgumentError(
      `"${raw}" is a Pinterest /${username}/ URL, not a board`,
      username.toLowerCase() === 'pin'
        ? 'Pass the board this pin lives on, e.g. janedoe/my-board (`opencli pinterest pin <id>` reports it)'
        : 'Pass <username>/<slug>, a board URL, or a numeric board id',
    );
  }
  return { username, slug, path: `/${username}/${slug}/` };
}

/** Normalize a username or profile URL to a bare username (Pinterest has no @-handles). */

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a full, well-formed board URL like https://www.pinterest.com/janedoe/my-board/
  2. Quote the URL in your shell so special characters don't break it
  3. Or skip the URL entirely and pass username/slug (janedoe/my-board) or a numeric board id
  4. Check for stray spaces/whitespace — trim the input before calling

Example fix

// before
await direct(process.env.BOARD_URL); // 'https://pinterest.com/janedoe/my board'
// after
const url = (process.env.BOARD_URL || '').trim().replace(/ /g, '-');
await direct(url); // or pass 'janedoe/my-board'
Defensive patterns

Strategy: validation

Validate before calling

function isParseableUrl(s) {
  if (typeof s !== 'string' || !/^https?:\/\//i.test(s.trim())) return true; // not a URL, other paths apply
  try { new URL(s.trim()); return true; } catch { return false; }
}
if (!isParseableUrl(boardRef)) boardRef = boardRef.trim(); // or reject before calling

Type guard

const isHttpUrl = (v) => {
  if (typeof v !== 'string' || !/^https?:\/\//i.test(v)) return false;
  try { new URL(v); return true; } catch { return false; }
};

Try / catch

let board;
try {
  board = tryParseBoardRef(input);
} catch (err) {
  if (err instanceof ArgumentError && err.message.startsWith('Invalid board URL')) {
    console.error(`${err.message} — ${err.hint}`);
    process.exitCode = 2;
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a string starting with http:// or https:// that new URL() rejects — e.g. 'https://pinterest com/janedoe/my-board' (space), 'https://', or a truncated/corrupted URL from a script.

Common situations: Shell splitting broke the URL at '&' or '?'; a template variable was empty producing 'https:///...'; smart quotes or invisible characters pasted from docs; an env var holding the board URL was only partially set.

Related errors


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