BerriAI/litellm · error · HTTPException

expires_after[seconds] must be a string, not a file upload

Error message

expires_after[seconds] must be a string, not a file upload

What it means

HTTPException(400) on file upload: expires_after[seconds] is not a string — the multipart part is an UploadFile or other non-string value where a numeric string is expected. The client must send the seconds as a plain text form field.

Source

Thrown at litellm/proxy/openai_files_endpoints/files_endpoints.py:413

                    status_code=400,
                    detail={
                        "error": "Both expires_after[anchor] and expires_after[seconds] must be provided if expires_after is specified",
                    },
                )

            # Validate expires_after[anchor] is a string (not UploadFile)
            if isinstance(expires_after_anchor, UploadFile):
                raise HTTPException(
                    status_code=400,
                    detail={
                        "error": "expires_after[anchor] must be a string, not a file upload",
                    },
                )

            # Validate expires_after[seconds] is a string (not UploadFile)
            # Use positive isinstance check for proper type narrowing (matches codebase pattern)
            if not isinstance(expires_after_seconds_str, str):
                raise HTTPException(
                    status_code=400,
                    detail={
                        "error": "expires_after[seconds] must be a string, not a file upload",
                    },
                )
            # After this check, mypy knows expires_after_seconds_str is str
            expires_after_seconds_str_validated: Final[str] = expires_after_seconds_str

            # Validate anchor is "created_at"
            if expires_after_anchor != "created_at":
                raise HTTPException(
                    status_code=400,
                    detail={
                        "error": f"expires_after[anchor] must be 'created_at', got '{expires_after_anchor}'",
                    },
                )

            # Convert seconds to int

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Send expires_after[seconds] as a string form field, not a file upload.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at litellm/proxy/openai_files_endpoints/files_endpoints.py:413 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/96212f057ce72852. Report an issue: GitHub.