odysseus-dev/odysseus · warning · HTTPException

No image

Error message

No image

What it means

HTTP 400 raised by POST /api/gallery/ai-upscale when the multipart form contains no 'image' field. Unlike the replace endpoint this check is only `if not file`, so a string value in the field would pass here and fail later in read_upload_limited; a wholly absent field fails immediately. The route also requires the can_generate_images privilege first.

Source

Thrown at routes/gallery/gallery_routes.py:568

                img_path.write_bytes(content)
                img.file_hash = hashlib.sha256(content).hexdigest()
                img.file_size = len(content)
                img.width, img.height = rotated.size
            db.commit()
            return {"ok": True, "width": img.width, "height": img.height}
        finally:
            db.close()

    # ---- POST /api/gallery/ai-upscale ----
    @router.post("/api/gallery/ai-upscale")
    async def gallery_ai_upscale(request: Request):
        """AI upscale using img2img with the diffusion server."""
        import base64, httpx

        user = require_privilege(request, "can_generate_images")
        form = await request.form()
        file = form.get("image")
        if not file: raise HTTPException(400, "No image")
        scale = int(form.get("scale", "2"))

        image_bytes = await read_upload_limited(file, GALLERY_TRANSFORM_UPLOAD_MAX_BYTES, "Image upload")
        b64 = base64.b64encode(image_bytes).decode()

        # Find image endpoint
        db = SessionLocal()
        try:
            ep = _first_visible_image_endpoint(db, user)
        finally:
            db.close()

        if not ep:
            raise HTTPException(400, "No image generation endpoint configured. Add one in Settings → Add Models.")

        base_url = ep.base_url.rstrip("/")
        if not base_url.endswith("/v1"):
            base_url += "/v1"

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Append the file as 'image' in multipart/form-data.
  2. Validate the file is selected before enabling the upscale button.
  3. Note the privilege gate: the user must have can_generate_images or the request fails earlier with 403.

Example fix

// before
fd.append('img', file); // wrong name -> 400
// after
fd.append('image', file); fd.append('scale', '2');
Defensive patterns

Strategy: validation

Validate before calling

if (!file) return showError('Choose an image to upscale');
const fd = new FormData(); fd.append('image', file); fd.append('scale', '2');

Type guard

const hasImagePart = (fd) => fd.get('image') != null;

Try / catch

try { await upscale(fd); } catch (e) { if (e.status === 400) showError('Attach the image in the "image" field'); }

Prevention

When it happens

Trigger: POST /api/gallery/ai-upscale with an empty form, a JSON body, or a FormData missing an 'image' part.

Common situations: Frontend reusing a FormData built for a different endpoint; file picker cleared before submit; curl without -F.

Related errors


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