BerriAI/litellm · error · HTTPException

Both expires_after[anchor] and expires_after[seconds] must b

Error message

Both expires_after[anchor] and expires_after[seconds] must be provided if expires_after is specified

What it means

HTTPException(400) on file upload: the expires_after field was partially supplied — only one of expires_after[anchor] or expires_after[seconds] is present. Both are required together to define the expiry policy, so the incomplete pair is rejected.

Source

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

        data = {}

        # Parse expires_after if provided
        expires_after: FileExpiresAfter | None = None
        form_data_raw: Final = await request.form()
        form_data_dict: Final[dict[str, Any]] = dict(form_data_raw)
        extracted_litellm_metadata: Final[dict[str, Any] | None] = extract_nested_form_metadata(
            form_data=form_data_dict, prefix="litellm_metadata["
        )
        expires_after_anchor: Final = form_data_raw.get("expires_after[anchor]")
        expires_after_seconds_str: Final = form_data_raw.get("expires_after[seconds]")

        # Add litellm_metadata to data if provided (from form field)
        if extracted_litellm_metadata is not None:
            data["litellm_metadata"] = extracted_litellm_metadata

        if expires_after_anchor is not None or expires_after_seconds_str is not None:
            if expires_after_anchor is None or expires_after_seconds_str is None:
                raise HTTPException(
                    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):

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Provide both expires_after[anchor] and expires_after[seconds], or omit expires_after entirely.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/openai_files_endpoints/files_endpoints.py:394 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/4f2a3f9f444c5275. Report an issue: GitHub.