Comfy-Org/ComfyUI · error · ValueError

INVALID_BODY

INVALID_BODY

Error message

tags are required for new asset uploads

What it means

Raised by the upload ingest path when the uploaded content is new (no existing asset with the same hash) and the request supplies no tags. For brand-new assets, tags are mandatory because they determine the write destination (the input/models/output role routing in resolve_destination_from_tags); known content short-circuits to reference-only creation and does not need them. Raised as ValueError, surfaced as INVALID_BODY.

Source

Thrown at app/assets/services/ingest.py:521

        result = _register_existing_asset(
            asset_hash=asset_hash,
            name=display_name,
            user_metadata=user_metadata or {},
            tags=tags or [],
            tag_origin="manual",
            owner_id=owner_id,
            mime_type=mime_type,
            preview_id=preview_id,
        )
        return UploadResult(
            ref=result.ref,
            asset=result.asset,
            tags=result.tags,
            created_new=False,
        )

    if not tags:
        raise ValueError("tags are required for new asset uploads")
    base_dir, subdirs = resolve_destination_from_tags(tags)
    dest_dir = os.path.join(base_dir, *subdirs) if subdirs else base_dir
    os.makedirs(dest_dir, exist_ok=True)

    src_for_ext = (client_filename or name or "").strip()
    _ext = os.path.splitext(os.path.basename(src_for_ext))[1] if src_for_ext else ""
    ext = _ext if 0 < len(_ext) <= 16 else ""
    hashed_basename = f"{digest}{ext}"
    dest_abs = os.path.abspath(os.path.join(dest_dir, hashed_basename))
    validate_path_within_base(dest_abs, base_dir)

    content_type = mime_type or (
        mimetypes.guess_type(os.path.basename(src_for_ext), strict=False)[0]
        or mimetypes.guess_type(hashed_basename, strict=False)[0]
        or "application/octet-stream"
    )

    try:

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Include at least one destination-role tag ('input', 'models', or 'output') with every new-asset upload — practically send tags on every upload.
  2. Check the error path: if your flow intentionally re-uploads known content without tags, ensure the hash matches so the reference-only path applies.
  3. Add a client-side check that refuses to submit an upload with an empty tag list.

Example fix

# before
files = {'file': open(path,'rb')}  # no tags field

# after
files = {'file': open(path,'rb')}
data = {'tags': ['input', 'user:alice']}
Defensive patterns

Strategy: validation

Validate before calling

def can_upload(tags: list[str]) -> bool:
    return bool(tags) and sum(t in {'input','models','output'} for t in tags) == 1

Prevention

When it happens

Trigger: POST /api/assets/upload with a file whose BLAKE3 hash is not already in the database and with an empty/missing tags list.

Common situations: Client sends tags only conditionally (e.g. only on retry); a bug that drops the tags form field; a caller assuming the server will default to the input directory.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/4746b7068e0178e8. Report an issue: GitHub.