{"record":{"id":"3471301e74b99b4b","repo":"Mintplex-Labs/anything-llm","slug":"image-edit-failed-res-status-body-res-s","errorCode":null,"errorMessage":"Image edit failed (${res.status}): ${body || res.statusText}","messagePattern":"Image edit failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/ImageGenerators/base.js","lineNumber":90,"sourceCode":"        this.imageFieldName(images.length),\n        new Blob([images[i]], { type: \"image/png\" }),\n        `reference-${i}.png`\n      );\n    }\n\n    const baseURL = this.client.baseURL.replace(/\\/+$/, \"\");\n    const res = await fetch(`${baseURL}/images/edits`, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.client.apiKey}`,\n      },\n      body: formData,\n      signal: signal ?? null,\n    });\n\n    if (!res.ok) {\n      const body = await res.text().catch(() => \"\");\n      throw new Error(\n        `Image edit failed (${res.status}): ${body || res.statusText}`\n      );\n    }\n\n    const payload = await res.json();\n    const image = payload?.data?.[0];\n    let result;\n    if (image?.b64_json) {\n      result = { buffer: Buffer.from(image.b64_json, \"base64\") };\n    } else if (image?.url) {\n      const imgRes = await fetch(image.url, { signal: signal ?? null });\n      if (!imgRes.ok)\n        throw new Error(`Failed to fetch edited image: ${imgRes.status}`);\n      result = { buffer: Buffer.from(await imgRes.arrayBuffer()) };\n    } else {\n      throw new Error(\"Image edit returned no image data.\");\n    }\n    this._sendImageTelemetry(\"image_generated\", {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/f92433b4ea0598492a1e6645ea22addbb4dd1287/server/utils/ImageGenerators/base.js#L72-L108","documentation":"BaseImageGenerator.editImage() builds a multipart form (model, prompt, size, n, and the reference image blobs) and POSTs it with raw fetch to the provider's OpenAI-compatible /v1/images/edits endpoint. Any non-2xx response throws this error, embedding the HTTP status plus the provider's body text (or statusText when the body is empty). The body is included so the provider's real reason stays visible.","triggerScenarios":"Using a model without an edits endpoint (dall-e-3, and most OpenAI-compatible servers that only implement images.generate); 401 from a missing/wrong image-gen key; 400/413 for oversized or non-PNG reference images; 404 when the provider does not route /v1/images/edits at all (Ollama's generator overrides editImage for exactly this reason).","commonSituations":"Switching IMAGE_GEN_MODEL_PREF to dall-e-3 and then attempting an image edit; pointing image generation at a self-hosted OpenAI-compatible gateway that never implemented edits; sending JPEG buffers where PNG is expected.","solutions":["Read the body inside the message — it is the provider's actual error text.","Use a model that supports the edits endpoint, i.e. gpt-image-1 (or dall-e-2 on OpenAI).","Confirm the provider actually serves POST /v1/images/edits; if not, use generation instead of editing.","Check auth (IMAGE_GEN_OPENAI_KEY or the provider's token env) and re-encode references as PNG under the size limit."],"exampleFix":"# .env — before (dall-e-3 exposes no edits endpoint)\nIMAGE_GEN_MODEL_PREF=dall-e-3\n\n# .env — after\nIMAGE_GEN_MODEL_PREF=gpt-image-1","handlingStrategy":"try-catch","validationCode":"const EDIT_CAPABLE_MODELS = new Set([\"gpt-image-1\", \"dall-e-2\"]);\nif (!EDIT_CAPABLE_MODELS.has(process.env.IMAGE_GEN_MODEL_PREF)) {\n  throw new Error(\n    `Model ${process.env.IMAGE_GEN_MODEL_PREF} does not support image edits — pick an edit-capable model.`\n  );\n}","typeGuard":"function isEditCapableModel(model) {\n  return typeof model === \"string\" && /^(gpt-image-1|dall-e-2)$/.test(model);\n}","tryCatchPattern":"try {\n  const image = await generator.editImage({ prompt, images, size, signal });\n} catch (err) {\n  const m = err.message.match(/^Image edit failed \\((\\d+)\\): ?([\\s\\S]*)$/);\n  if (m) {\n    const [_, status, body] = m;\n    // 401 → fix the image-gen key; 404 → provider has no edits endpoint; 400/413 → invalid/oversized input\n  } else {\n    throw err;\n  }\n}","preventionTips":["Only offer image-edit UI when the active model/provider implements /v1/images/edits.","Convert reference images to PNG and cap their size before upload.","Always read the embedded response body — it carries the provider's real reason."],"tags":["image-generation","image-edit","http-status","openai-compatible"],"backgroundTag":"api-request-failed","analyzedSha":"f92433b4ea0598492a1e6645ea22addbb4dd1287","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}