{"record":{"id":"041ac8bbeaee28b9","repo":"jackwener/OpenCLI","slug":"api-error-041ac8","errorCode":"API_ERROR","errorMessage":"API_ERROR","messagePattern":"API_ERROR","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/yollomi/utils.js","lineNumber":57,"sourceCode":"          body: ${JSON.stringify(bodyJson)},\n        });\n        const text = await res.text();\n        return { ok: res.ok, status: res.status, body: text };\n      } catch (err) {\n        return { ok: false, status: 0, body: err.message || 'fetch failed (on ' + location.href + ')' };\n      }\n    })()\n  `);\n    if (!result || result.status === 0) {\n        throw new CliError('FETCH_ERROR', `Network error: ${result?.body || 'Failed to fetch'}`, 'Make sure Chrome is logged in to https://yollomi.com and the Browser Bridge is running');\n    }\n    if (!result.ok) {\n        let detail = result.body;\n        try {\n            detail = JSON.parse(result.body)?.error || JSON.parse(result.body)?.message || result.body;\n        }\n        catch { }\n        throw new CliError('API_ERROR', `Yollomi API ${result.status}: ${detail}`, result.status === 401\n            ? 'Not logged in — open Chrome, go to https://yollomi.com and log in'\n            : result.status === 402\n                ? 'Insufficient credits — top up at https://yollomi.com/pricing'\n                : result.status === 429\n                    ? 'Rate limited — wait a moment and retry'\n                    : 'Check the model and parameters');\n    }\n    try {\n        return JSON.parse(result.body);\n    }\n    catch {\n        throw new CliError('API_ERROR', 'Invalid JSON response', 'Try again');\n    }\n}\n/**\n * Resolve an image input: local file → base64 data URL, URL → as-is.\n */\nexport function resolveImageInput(input) {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/yollomi/utils.js#L39-L75","documentation":"API_ERROR (HTTP variant) is thrown by yollomiPost when the server responded but with a non-ok status. The message includes the status code and any error/message detail parsed from the JSON body; the fix hint is status-specific: 401 → not logged in, 402 → out of credits, 429 → rate limited, otherwise check parameters.","triggerScenarios":"Any yollomi command using yollomiPost (generate, upscale, video, ...) where the in-page fetch returns ok=false with an HTTP status — 401 (no/expired session), 402 (insufficient credits), 429 (too many requests), 400/500 (bad params or server fault).","commonSituations":"Session cookie expired after long idle (401), heavy usage draining credits (402), batch scripts hammering the API (429), or unsupported modelId/parameters after an API update (400).","solutions":["Read the status in the message: 401 → log in to yollomi.com in the bridged Chrome; 402 → top up credits at yollomi.com/pricing; 429 → wait and retry with backoff","For other statuses, verify the modelId and parameters against current API docs — the body detail string is included in the error","Re-authenticate if the session expired, then rerun the command","Add spacing/retries between calls in scripts to avoid 429"],"exampleFix":"// before\nfor (const p of prompts) await generate(page, p);  // 429 after burst\n// after\nfor (const p of prompts) {\n  await generate(page, p);\n  await new Promise(r => setTimeout(r, 2000));  // throttle to avoid rate limit\n}","handlingStrategy":"retry","validationCode":"// Pre-flight: confirm session and credits by loading the site in the bridged page\n// and only proceed when a yollomi.com session cookie exists (no login redirect).","typeGuard":"null","tryCatchPattern":"try {\n  await yollomiPost(page, endpoint, body);\n} catch (e) {\n  if (e.code !== 'API_ERROR') throw e;\n  const status = parseInt(e.message.match(/API (\\d{3})/)?.[1] ?? '0', 10);\n  if (status === 429) { await sleep(5000); return retry(); }\n  if (status === 401) throw new Error('Log in to yollomi.com first');\n  if (status === 402) throw new Error('Top up credits at yollomi.com/pricing');\n  throw e;\n}","preventionTips":["Throttle request rate in scripts to avoid 429","Monitor credit balance before large batches","Re-authenticate when sessions age out","Validate modelId/parameters against current API docs"],"tags":["api","http-status","rate-limit","authentication","credits"],"backgroundTag":"http-api-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}