invoke-ai/InvokeAI · error · HTTPException

Invalid preset data

Error message

Invalid preset data

What it means

update_style_preset (PATCH style preset) parses the multipart 'data' form field as JSON and validates it against the StylePresetFormData pydantic model. If the string is not valid JSON or the parsed object fails schema validation (missing/extra/ill-typed fields), the endpoint returns HTTP 400 with detail 'Invalid preset data'. It is a request-body contract error, not a server fault.

Source

Thrown at invokeai/app/api/routers/style_presets.py:120

    image: Optional[UploadFile] = File(description="The image file to upload", default=None),
    style_preset_id: str = Path(description="The id of the style preset to update"),
    data: str = Form(description="The data of the style preset to update"),
) -> StylePresetRecordWithImage:
    """Updates a style preset"""
    # Validate the data payload BEFORE any image-state mutation so a malformed
    # request can't leave the preset image partially updated.
    try:
        parsed_data = json.loads(data)
        validated_data = StylePresetFormData(**parsed_data)

        name = validated_data.name
        type = validated_data.type
        positive_prompt = validated_data.positive_prompt
        negative_prompt = validated_data.negative_prompt
        is_public = validated_data.is_public

    except (json.JSONDecodeError, pydantic.ValidationError):
        raise HTTPException(status_code=400, detail="Invalid preset data")

    record = await asyncio.to_thread(_load_record_or_404, style_preset_id)
    _assert_preset_write(record, current_user)

    if image is not None:
        if not image.content_type or not image.content_type.startswith("image"):
            raise HTTPException(status_code=415, detail="Not an image")

        contents = await image.read()
        try:
            pil_image = await asyncio.to_thread(Image.open, io.BytesIO(contents))

        except Exception:
            ApiDependencies.invoker.services.logger.error(traceback.format_exc())
            raise HTTPException(status_code=415, detail="Failed to read image")

        try:
            await asyncio.to_thread(

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Print/log the exact 'data' string sent and run json.loads on it client-side to confirm it is valid JSON.
  2. Validate the payload against StylePresetFormData (name, type, positive_prompt, negative_prompt, is_public) with the same pydantic model or the generated OpenAPI client type before sending.
  3. Ensure the field is sent as a single multipart form part named 'data' containing a JSON string, not as separate form fields.
  4. Regenerate the API client from the server's OpenAPI schema so the form schema matches the running server version.

Example fix

// before
curl -X PATCH .../style_presets/i/abc -F name="My preset" -F type="user"

// after
curl -X PATCH .../style_presets/i/abc \
  -F 'data={"name":"My preset","type":"user","positive_prompt":"...","negative_prompt":"...","is_public":false}'
Defensive patterns

Strategy: validation

Validate before calling

import json

def validate_preset_payload(data_str: str) -> dict:
    payload = json.loads(data_str)  # raises JSONDecodeError -> would be 400
    required = {"name": str, "type": str, "positive_prompt": str, "negative_prompt": str, "is_public": bool}
    for key, typ in required.items():
        assert key in payload and isinstance(payload[key], typ), f"bad field: {key}"
    return payload

validate_preset_payload(data_field)  # run before PATCH/POST

Type guard

def is_valid_preset_data(v: object) -> TypeGuard[dict]:
    return (
        isinstance(v, dict)
        and isinstance(v.get("name"), str)
        and isinstance(v.get("type"), str)
        and isinstance(v.get("positive_prompt"), str)
        and isinstance(v.get("negative_prompt"), str)
        and isinstance(v.get("is_public"), bool)
    )

Try / catch

try {
  await api.updateStylePreset({ stylePresetId, data: JSON.stringify(preset), image });
} catch (e) {
  if (e.status === 400 && e.detail === "Invalid preset data") {
    console.error("Payload failed schema:", JSON.stringify(preset));
  } else throw e;
}

Prevention

When it happens

Trigger: PATCH /style_presets/i/{id} with multipart form where: data is not parseable JSON (truncated, single quotes, HTML error page), data omits a required StylePresetFormData field (name, type, positive_prompt, negative_prompt, is_public), or a field has the wrong type (e.g. is_public as string 'true' instead of boolean, unknown preset type enum value).

Common situations: Client builds the data field with JSON.stringify omitted (sends '[object Object]' or a Python dict repr); content-type confusion causing double-encoded JSON strings; SDK version drift where StylePresetFormData gained or renamed fields; hand-written curl tests sending raw key=value instead of JSON.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/9a31315d56b570da. Report an issue: GitHub.