odysseus-dev/odysseus · error · HTTPException

MLX image generator completed but did not write

Error message

MLX image generator completed but did not write {out_path}

What it means

Raised in /v1/images/generations of scripts/mlx_image_server.py with HTTP 500 when the generation subprocess (mflux CLI, HiDream script, or Boogu in-process call) reported success but the expected output file out_path (a temp dir image.png) was not created. It guards the contract that every backend must write the output path it was given.

Solutions

  1. Reproduce the exact logged command manually and check where output lands
  2. Upgrade/align the backend version with what the server expects for --output
  3. Freeze/inspect the temp dir (replace TemporaryDirectory with a kept dir) to see whether the file appears then vanishes
  4. Check disk space and temp dir permissions on the host
Defensive patterns

Strategy: fallback

Validate before calling

# server-side guard: verify backend writes before accepting traffic
subprocess.run([cli, '--model', m, '--prompt', 'smoke', '--steps', '1', '--output', '/tmp/probe.png'], check=True)
assert pathlib.Path('/tmp/probe.png').exists()

Try / catch

try:
    gen_and_read(out_path)
except HTTPException as e:
    if 'did not write' in str(e.detail):
        out_path = run_backend_manually_and_locate_output()  # fallback path
    else:
        raise

Prevention

When it happens

Trigger: A backend exits 0 without producing the file: CLI wrote to a different location (output flag mishandled), HiDream script saved elsewhere or silently skipped saving, Boogu path failed to save without raising, or temp-dir permission issues.

Common situations: Version change in mflux/HiDream script renaming the --output semantics; quantized forks that print instead of save; sandboxed temp dirs cleaned mid-run; disk-full so the save silently no-ops in the child.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/44e19cf8652c7b89. Report an issue: GitHub.

Appendix: source

Thrown at scripts/mlx_image_server.py:380

                if _args.base_model:
                    cmd += ["--base-model", _args.base_model]
                if _args.lora_style:
                    cmd += ["--lora-style", _args.lora_style]
                if _args.lora_paths:
                    cmd += ["--lora-paths", *_args.lora_paths]
                lora_scales = _valid_numbers(_args.lora_scales)
                if lora_scales:
                    cmd += ["--lora-scales", *lora_scales]
                if "qwen" not in model.lower():
                    cmd += ["--width", str(width), "--height", str(height)]
                env = os.environ.copy()
                proc = subprocess.run(cmd, env=env, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                if proc.returncode != 0:
                    detail = (proc.stderr or proc.stdout or f"{cli} failed").strip()
                    logger.error("MLX image command failed (%s): %s\n%s", proc.returncode, " ".join(cmd), detail[-4000:])
                    raise HTTPException(500, detail[-4000:])
            if not out_path.exists():
                raise HTTPException(500, f"MLX image generator completed but did not write {out_path}")
            b64 = base64.b64encode(out_path.read_bytes()).decode("ascii")
            out_images.append({"b64_json": b64})
    return {"created": 0, "data": out_images}


@app.post("/v1/images/edits")
async def edit_image(
    image: UploadFile = File(...),
    mask: UploadFile | None = File(None),
    prompt: str = Form(""),
    model: str = Form(""),
    n: int = Form(1),
    size: str = Form("1024x1024"),
    response_format: str = Form("b64_json"),
):
    active_model = model or _args.model
    if _is_lama_inpaint(active_model) or _is_ddcolor(active_model):
        image_raw = await image.read()

View on GitHub (pinned to f9235ebbf1)