jackwener/OpenCLI · error · ArgumentError
"${raw}" is a Pinterest /${username}/ URL, not a board
Error message
"${raw}" is a Pinterest /${username}/ URL, not a board What it means
tryParseBoardRef rejects Pinterest URLs whose first path segment is a reserved root such as /pin/ rather than a username. Those URLs point at pins or other Pinterest resources, not boards, so throwing prevents silently misinterpreting the reference. The hint for /pin/ URLs points users at `opencli pinterest pin <id>` to discover the owning board.
Source
Thrown at clis/pinterest/utils.js:82
* 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). */
export function parseUsername(raw) {
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/');View on GitHub (pinned to 49907e53dc)
Solutions
- If it's a /pin/ URL, run `opencli pinterest pin <id>` to find the board, then pass that board
- Pass the board as username/slug, e.g. janedoe/my-board
- Pass the board's canonical URL https://www.pinterest.com/<user>/<slug>/
- Pass the numeric board id instead of a resource URL
Example fix
// before
await direct('https://www.pinterest.com/pin/1234567890123456/');
// after
await direct('janedoe/my-board'); // board the pin lives on Defensive patterns
Strategy: validation
Validate before calling
const RESERVED = new Set(['pin', 'search', 'today', 'ideas', 'resource']);
function looksLikeBoardUrl(s) {
if (!/^https?:\/\//i.test(s || '')) return true;
const seg = new URL(s).pathname.split('/').filter(Boolean)[0];
return seg ? !RESERVED.has(seg.toLowerCase()) : false;
} Type guard
const isPinUrl = (v) => typeof v === 'string' && /(^|\/)pin\/\d+/.test(v);
Try / catch
try {
ref = tryParseBoardRef(input);
} catch (err) {
if (err instanceof ArgumentError && /not a board/.test(err.message)) {
console.error(`${err.message}\n${err.hint}`); // hint says to use `pinterest pin <id>`
process.exitCode = 2;
} else throw err;
} Prevention
- Detect /pin/ URLs first and route them to the pin API, not board parsing
- Extract the board from a pin lookup (opencli pinterest pin <id>) before board calls
- Sanction only canonical board URLs of the form /<user>/<slug>/
- When sharing links internally, copy the board URL, not the current page URL
When it happens
Trigger: Passing https://www.pinterest.com/pin/1234567890123456/ (or another reserved root like /search/, /today/) to a board-parsing command; the first path segment lowercased is in RESERVED_PATH_ROOTS.
Common situations: Copying a pin URL from the browser when you meant the board URL; sharing links from an email that point at pins; automation that always pastes the current page URL.
Related errors
- '${rawInput}' does not look like an autohome series id (a nu
- bilibili follow target must be a valid space.bilibili.com/<u
- chatgpt project commands require a chatgpt.com project id or
- Invalid Chess.com game URL: "${value}" Expected https://www.
- event query parameter must be a numeric event id
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d944f1388d914af4.
Report an issue: GitHub.