{"record":{"id":"9927c13b229cc436","repo":"jackwener/OpenCLI","slug":"image-url-must-be-http-s-value","errorCode":null,"errorMessage":"image URL must be http(s): ${value}","messagePattern":"image URL must be http\\(s\\): (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/pin-create.js","lineNumber":16,"sourceCode":"// Pinterest pin-create — create a pin from a remote image URL onto a board (PinResource/create).\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { PINTEREST_BASE, movePinToSection, pinterestResourceCreate, resolveBoardId, resolveBoardTarget, resolveSection } from './utils.js';\n\nfunction requireImageUrl(raw) {\n  const value = String(raw ?? '').trim();\n  if (!value) throw new ArgumentError('image is required (a remote image URL)');\n  let parsed;\n  try {\n    parsed = new URL(value);\n  } catch {\n    throw new ArgumentError(`image must be a remote image URL (got \"${raw}\")`);\n  }\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n    throw new ArgumentError(`image URL must be http(s): ${value}`);\n  }\n  return value;\n}\n\ncli({\n  site: 'pinterest',\n  name: 'pin-create',\n  access: 'write',\n  description: 'Create a pin from a remote image URL onto a board',\n  domain: 'www.pinterest.com',\n  strategy: Strategy.COOKIE,\n  args: [\n    { name: 'image', type: 'string', positional: true, required: true, help: 'Direct image URL Pinterest can fetch (not a page URL), e.g. https://example.com/image.jpg' },\n    { name: 'board', type: 'string', required: true, help: 'Target board: <username>/<slug>, board URL, or board id (a new pin always needs a board)' },\n    { name: 'section', type: 'string', default: '', help: 'Optional board section id or slug' },\n    { name: 'title', type: 'string', default: '', help: 'Pin title' },\n    // Pinterest ignores description for scraped pins (it derives one from the source page).\n    { name: 'description', type: 'string', default: '', help: 'Pin description (Pinterest may override it for scraped images)' },","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/pin-create.js#L1-L34","documentation":"This ArgumentError is thrown by requireImageUrl in clis/pinterest/pin-create.js when the --image positional argument parses as a valid URL but its protocol is not http: or https:. Pinterest can only fetch remote images over HTTP(S) (method 'scraped'), so schemes like file:, data:, ftp: or javascript: are rejected before any network call is made.","triggerScenarios":"Calling `pin-create` with an image argument whose URL scheme is non-http(s), e.g. `file:///home/user/pic.png`, `data:image/png;base64,...`, `ftp://host/img.jpg`. The URL must parse via `new URL()` but fail the protocol check at clis/pinterest/pin-create.js:15-17.","commonSituations":"Passing a local file path like `/home/me/photo.jpg` (on Windows `C:\\pics\\a.jpg` may even parse as a URL with scheme `c:`); embedding a base64 data URI expecting upload behavior; using an internal scheme from another tool's config.","solutions":["Replace the argument with a publicly reachable http:// or https:// direct image URL (e.g. https://example.com/image.jpg), not a local path or data URI","If the image is local, upload it to a host (or an image CDN/object storage with a public URL) first and pass that URL","If you passed an HTML page URL, use the direct image file URL instead — the help text says Pinterest fetches the image itself","Check for typo'd schemes such as `http:/example.com/i.jpg` or leading characters that make `new URL` pick up the wrong protocol"],"exampleFix":"// before\n$ opencli pinterest pin-create file:///tmp/photo.jpg --board me/ideas\n// after\n$ opencli pinterest pin-create https://cdn.example.com/photo.jpg --board me/ideas","handlingStrategy":"validation","validationCode":"function assertHttpImageUrl(url) {\n  const parsed = new URL(String(url ?? '').trim());\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n    throw new Error(`image URL must be http(s): ${url}`);\n  }\n  return parsed.href;\n}","typeGuard":"function isHttpImageUrl(value) {\n  try {\n    const u = new URL(String(value).trim());\n    return u.protocol === 'http:' || u.protocol === 'https:';\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await run(['pin-create', imageUrl, '--board', board]);\n} catch (e) {\n  if (/image URL must be http\\(s\\)/.test(e.message)) {\n    throw new Error(`Upload ${imageUrl} to a web host first; local/data URLs are not accepted`);\n  }\n  throw e;\n}","preventionTips":["Always pass direct http(s) image file URLs, never local paths, file:// or data: URIs","Validate the scheme with new URL() before invoking the command","Upload local images to object storage/CDN first and use the public URL","Watch for Windows paths like C:\\... whose drive letter parses as a URL scheme"],"tags":["validation","argument-error","url-protocol","pinterest"],"backgroundTag":"invalid-url-protocol","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}