Mintplex-Labs/anything-llm · error

Image edit failed ( )

Error message

Image edit failed (${res.status}): ${body || res.statusText}

What it means

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.

Solutions

  1. Read the body inside the message — it is the provider's actual error text.
  2. Use a model that supports the edits endpoint, i.e. gpt-image-1 (or dall-e-2 on OpenAI).
  3. Confirm the provider actually serves POST /v1/images/edits; if not, use generation instead of editing.
  4. Check auth (IMAGE_GEN_OPENAI_KEY or the provider's token env) and re-encode references as PNG under the size limit.

Example fix

# .env — before (dall-e-3 exposes no edits endpoint)
IMAGE_GEN_MODEL_PREF=dall-e-3

# .env — after
IMAGE_GEN_MODEL_PREF=gpt-image-1
Defensive patterns

Strategy: try-catch

Validate before calling

const EDIT_CAPABLE_MODELS = new Set(["gpt-image-1", "dall-e-2"]);
if (!EDIT_CAPABLE_MODELS.has(process.env.IMAGE_GEN_MODEL_PREF)) {
  throw new Error(
    `Model ${process.env.IMAGE_GEN_MODEL_PREF} does not support image edits — pick an edit-capable model.`
  );
}

Type guard

function isEditCapableModel(model) {
  return typeof model === "string" && /^(gpt-image-1|dall-e-2)$/.test(model);
}

Try / catch

try {
  const image = await generator.editImage({ prompt, images, size, signal });
} catch (err) {
  const m = err.message.match(/^Image edit failed \((\d+)\): ?([\s\S]*)$/);
  if (m) {
    const [_, status, body] = m;
    // 401 → fix the image-gen key; 404 → provider has no edits endpoint; 400/413 → invalid/oversized input
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@f92433b4ea (2026-08-18). Data as JSON: /api/errors/3471301e74b99b4b. Report an issue: GitHub.

Appendix: source

Thrown at server/utils/ImageGenerators/base.js:90

        this.imageFieldName(images.length),
        new Blob([images[i]], { type: "image/png" }),
        `reference-${i}.png`
      );
    }

    const baseURL = this.client.baseURL.replace(/\/+$/, "");
    const res = await fetch(`${baseURL}/images/edits`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${this.client.apiKey}`,
      },
      body: formData,
      signal: signal ?? null,
    });

    if (!res.ok) {
      const body = await res.text().catch(() => "");
      throw new Error(
        `Image edit failed (${res.status}): ${body || res.statusText}`
      );
    }

    const payload = await res.json();
    const image = payload?.data?.[0];
    let result;
    if (image?.b64_json) {
      result = { buffer: Buffer.from(image.b64_json, "base64") };
    } else if (image?.url) {
      const imgRes = await fetch(image.url, { signal: signal ?? null });
      if (!imgRes.ok)
        throw new Error(`Failed to fetch edited image: ${imgRes.status}`);
      result = { buffer: Buffer.from(await imgRes.arrayBuffer()) };
    } else {
      throw new Error("Image edit returned no image data.");
    }
    this._sendImageTelemetry("image_generated", {

View on GitHub (pinned to f92433b4ea)