{"record":{"id":"0ed835e5f7f5b630","repo":"jackwener/OpenCLI","slug":"pinterest-request-failed-http-status-detail","errorCode":null,"errorMessage":"Pinterest request failed (HTTP ${status})${detail}${hint}","messagePattern":"Pinterest request failed \\(HTTP (.+?)\\)(.+?)(.+?)","errorType":"http","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/utils.js","lineNumber":226,"sourceCode":"  }\n  if (raw?.__httpError) {\n    const status = raw.__httpError;\n    // Reads work anonymously, so their 403 is a rejected request, not a login prompt;\n    // writes genuinely need login, so treat their 403 as auth too.\n    if (status === 401 || (WRITE_ACTIONS.has(action) && status === 403)) {\n      // Pinterest also answers 401 for writes it refuses on a logged-in session (e.g. editing the\n      // link of a scraped pin), so pass its own message through instead of only saying \"log in\".\n      throw new AuthRequiredError(\n        PINTEREST_DOMAIN,\n        raw.message\n          ? `Pinterest refused this write: ${raw.message}`\n          : 'This action requires being logged in to Pinterest in Chrome',\n      );\n    }\n    const hint = status === 403 ? ' (missing or expired CSRF token — reload Pinterest in Chrome)' : '';\n    // Surface Pinterest's own error text (from resource_response.error.message) when present.\n    const detail = raw.message ? `: ${raw.message}` : '';\n    throw new CommandExecutionError(`Pinterest request failed (HTTP ${status})${detail}${hint}`);\n  }\n  if (!raw || typeof raw !== 'object' || raw.__malformed) {\n    throw new CommandExecutionError('Pinterest request returned malformed JSON payload');\n  }\n  const resourceResponse = raw.resource_response;\n  if (!resourceResponse || typeof resourceResponse !== 'object') {\n    throw new CommandExecutionError('Pinterest request returned malformed API payload');\n  }\n  const payload = resourceResponse.data;\n  const results = Array.isArray(payload)\n    ? payload\n    : (payload && Array.isArray(payload.results) ? payload.results : []);\n  return { data: payload, results, bookmark: resourceResponse.bookmark || null };\n}\n\n/** POST a /create/ mutation; returns the created resource_response.data. */\nexport async function pinterestResourceCreate(page, resource, options, sourceUrl) {\n  const { data } = await pinterestResourceFetch(page, resource, options, sourceUrl, 'create');","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/utils.js#L208-L244","documentation":"Pinterest's resource endpoint returned a non-2xx status that is not classified as auth (not 401, and not 403-on-write). The library throws CommandExecutionError including Pinterest's own error message when present and a CSRF hint for 403 responses.","triggerScenarios":"HTTP 404 for a nonexistent resource (bad board/pin lookup); HTTP 403 on a read when the csrftoken is missing/expired; HTTP 429 rate limiting; HTTP 5xx from Pinterest; any other unexpected status.","commonSituations":"Rate limiting after rapid scripted calls (429); expired CSRF token causing 403 on reads; typos in board username/slug causing 404; Pinterest transient outages (5xx).","solutions":["Read the detail/hint in the message — 403 means reload Pinterest in Chrome to refresh the CSRF token","If 429, wait and back off before retrying; slow down scripted call rates","If 404, verify the username/slug or pin exists","Retry later for 5xx Pinterest-side errors"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { const r = await cmd.userBoards(u); } catch (e) { const m = e.message.match(/HTTP (\\d+)/); if (m && m[1] === '429') { await sleep(60000); return retry(); } if (m && m[1] === '403') console.error('Reload Pinterest in Chrome to refresh CSRF'); throw e; }","preventionTips":["Throttle scripted calls to avoid 429 rate limits","Reload Pinterest in Chrome periodically to keep the CSRF token fresh","Verify board/pin identifiers to avoid 404s","Treat 5xx as transient and retry with backoff"],"tags":["http-error","rate-limit","csrf","pinterest"],"backgroundTag":"http-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}