{"record":{"id":"881968eae771e53c","repo":"jackwener/OpenCLI","slug":"pin-id-is-required","errorCode":null,"errorMessage":"pin id is required","messagePattern":"pin id is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/utils.js","lineNumber":120,"sourceCode":"  }\n  value = value.replace(/^\\/+|\\/+$/g, '');\n  if (!value) throw new ArgumentError(`Not a username: \"${raw}\"`, 'Pass the bare username, e.g. janedoe');\n  if (value.includes('/')) {\n    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) {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/utils.js#L102-L138","documentation":"parsePinId parses a bare numeric pin id or a /pin/<id>/ URL into a pin id string. It throws this ArgumentError when the input is empty or whitespace-only, since there is no id to extract. Failing fast avoids issuing a request to an undefined pin endpoint.","triggerScenarios":"Calling parsePinId(''), parsePinId(null), parsePinId(undefined), or parsePinId('   ') — e.g. an id/sourcePinId argument that was never provided.","commonSituations":"Forgot to pass the pin id to the CLI command; an upstream lookup returned nothing so the variable was empty; JSON config key missing so undefined was passed; a script loop where one row lacked an id.","solutions":["Pass a numeric pin id, e.g. 1234567890123456","Or pass a /pin/<id>/ URL like https://www.pinterest.com/pin/1234567890123456/","Verify the upstream data/config actually contains the pin id before calling","Add an early existence check and skip/handle rows with missing ids"],"exampleFix":"// before\nconst id = parsePinId(row.pinId); // may be ''\n// after\nif (!row.pinId) { console.warn('skipping row without pinId'); return; }\nconst id = parsePinId(row.pinId);","handlingStrategy":"validation","validationCode":"const id = String(raw ?? '').trim();\nif (!id) throw new Error('pin id missing');\nconst isPinRef = /^\\d+$/.test(id) || /\\/pin\\/(\\d+)/.test(id);\nif (!isPinRef) throw new Error(`not a pin id or pin URL: ${id}`);","typeGuard":"const isPinIdLike = (v) => {\n  const s = String(v ?? '').trim();\n  return /^\\d+$/.test(s) || /\\/pin\\/(\\d+)/.test(s);\n};","tryCatchPattern":"let pinId;\ntry {\n  pinId = parsePinId(input);\n} catch (err) {\n  if (err instanceof ArgumentError && err.message === 'pin id is required') {\n    console.error('Usage: ... <pinId|pin-url>');\n    process.exitCode = 2;\n  } else throw err;\n}","preventionTips":["Make the pin id a required CLI argument so omission fails at parse time","Guard loops: skip rows with missing ids and log them","Check upstream lookups returned a value before propagating it","Validate JSON config keys exist at startup before any API calls"],"tags":["validation","argument-error","missing-argument","pin-id"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}