{"record":{"id":"d27fd555597c4160","repo":"jackwener/OpenCLI","slug":"not-a-pin-id-or-pin-url-raw","errorCode":null,"errorMessage":"Not a pin id or pin URL: \"${raw}\"","messagePattern":"Not a pin id or pin URL: \"(.+?)\"","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/utils.js","lineNumber":124,"sourceCode":"    throw new ArgumentError(\n      `Not a username: \"${raw}\"`,\n      'This looks like a board or pin reference — pass just the username, e.g. janedoe',\n    );\n  }\n  if (value.startsWith('@')) {\n    throw new ArgumentError(`Pinterest usernames have no \"@\": \"${raw}\"`, 'Drop the @ and use the bare username, e.g. janedoe');\n  }\n  return value;\n}\n\n/** Parse a bare pin id or a /pin/<id>/ URL. */\nexport function parsePinId(raw) {\n  const value = String(raw ?? '').trim();\n  if (!value) throw new ArgumentError('pin id is required', 'Pass a pin id or /pin/<id>/ URL, e.g. 1234567890123456');\n  if (/^\\d+$/.test(value)) return value;\n  const match = value.match(/\\/pin\\/(\\d+)/);\n  if (match) return match[1];\n  throw new ArgumentError(`Not a pin id or pin URL: \"${raw}\"`, 'Expected a numeric id or a /pin/<id>/ URL, e.g. 1234567890123456');\n}\n\n/** Highest-resolution image URL available for a pin. */\nexport function pickPinImage(images) {\n  if (!images || typeof images !== 'object') return '';\n  for (const key of ['orig', '736x', '564x', '474x', '236x']) {\n    const candidate = images[key];\n    if (candidate && candidate.url) return candidate.url;\n  }\n  return '';\n}\n\n/** Map a raw pin to the shared grid-row shape used by list commands. */\nexport function toPinRow(pin) {\n  const id = String(pin.id ?? '');\n  return {\n    pinId: id,\n    title: (pin.title || pin.grid_title || '').trim(),","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/utils.js#L106-L142","documentation":"parsePinId validates that its argument is either a numeric Pinterest pin id or a /pin/<id>/ URL. It throws ArgumentError when the value is non-empty but matches neither pattern, because downstream Pinterest resource calls require a real pin id.","triggerScenarios":"Calling id(pin) or sourcePinId(pin) with a display name, a slug like 'my-cool-pin', a full pin URL without a numeric id (e.g. https://pinterest.com/pin/ with the id stripped), a URL-encoded or whitespace-padded garbage string, or passing a pin object/string instead of an id.","commonSituations":"Copy-pasting a pin title or description instead of the id; extracting the URL with a regex that dropped the numeric path segment; passing a board pin item's 'title' field rather than its 'id'; localization suffixes in URLs; users typing 'pin/12345' without leading slash so the /pin/ regex doesn't match... (note 'pin/12345' actually fails because the regex requires '/pin/').","solutions":["Pass the numeric pin id, e.g. 1234567890123456","Pass the full /pin/<id>/ URL copied from the browser address bar","If you have a pin object, extract its id field before calling","Trim whitespace and strip query strings from the URL before passing"],"exampleFix":"// before\nawait cmd.id('my summer mood board pin');\n// after\nawait cmd.id('https://www.pinterest.com/pin/1234567890123456/');","handlingStrategy":"validation","validationCode":"function isValidPinRef(v){const s=String(v??'').trim();return /^\\d+$/.test(s)||/\\/pin\\/(\\d+)/.test(s);}","typeGuard":"function isPinId(v){return typeof v==='string'&&/^\\d+$/.test(v.trim());}","tryCatchPattern":"try { const pinId = await cmd.id(rawPin); } catch (e) { if (e instanceof ArgumentError) console.error(`Bad pin ref: ${rawPin}`); else throw e; }","preventionTips":["Always extract the id field from pin objects instead of passing titles","Copy pin URLs directly from the address bar including /pin/<id>/","Validate with a numeric regex before calling","Strip query strings and trim whitespace from URLs"],"tags":["argument-validation","input-parsing","pinterest"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}