PrefectHQ/fastmcp · error · ValueError

File exceeds max size ( > )

Error message

File {f.get('name', '?')!r} exceeds max size ({_format_size(actual_size)} > {_format_size(provider._max_file_size)})

What it means

When files are uploaded, store_files computes the real size from the base64 payload (not the client-reported size) and rejects any file larger than the provider's configured _max_file_size with this ValueError. This guards memory and storage from oversized uploads.

Solutions

  1. Reduce the file size before uploading (compress, crop, or split the file).
  2. Raise the configured max_file_size on the FileUpload provider if policy allows.
  3. Check the size limit client-side before uploading to give users early feedback.

Example fix

// before
FileUpload(max_file_size=1_000_000)
# uploading a 5 MB file fails
// after
FileUpload(max_file_size=10_000_000)  # or compress the file to < 1 MB
Defensive patterns

Strategy: validation

Validate before calling

import base64, os
MAX = provider_max_file_size
if os.path.getsize(path) > MAX:
    raise ValueError(f"{path} exceeds {MAX} bytes; compress or split before upload")
data = base64.b64encode(open(path, 'rb').read()).decode()
if _b64_decoded_size(data) > MAX:
    raise ValueError("decoded payload still exceeds limit")

Try / catch

try:
    store_upload(files)
except ValueError as e:
    if "exceeds max size" in str(e):
        compress_and_retry(files, target=max_file_size)

Prevention

When it happens

Trigger: Uploading a file whose decoded byte size exceeds provider._max_file_size to the FileUpload app's store tool.

Common situations: Users uploading large documents/images; the app configured with a small max_file_size; a client lying about the `size` field (the real base64-derived size is checked).

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/b5ee381ca8dfa3ba. Report an issue: GitHub.

Appendix: source

Thrown at fastmcp_slim/fastmcp/apps/file_upload.py:290

            result["content_base64"] = entry["data"][:200] + "..."
        return result

    # ------------------------------------------------------------------
    # Tool registration
    # ------------------------------------------------------------------

    def _register_tools(self) -> None:
        provider = self

        @self.tool()
        def store_files(files: list[dict], ctx: Context) -> list[dict]:
            """Store uploaded files. Receives file objects with name, size, type, data (base64)."""
            for f in files:
                # Compute actual data size from the base64 payload rather
                # than trusting the client-reported ``size`` field.
                actual_size = _b64_decoded_size(f.get("data", ""))
                if actual_size > provider._max_file_size:
                    raise ValueError(
                        f"File {f.get('name', '?')!r} exceeds max size "
                        f"({_format_size(actual_size)} > "
                        f"{_format_size(provider._max_file_size)})"
                    )
            return provider.on_store(files, ctx)

        @self.tool(model=True)
        def list_files(ctx: Context) -> list[dict]:
            """List all uploaded files with metadata."""
            return provider.on_list(ctx)

        @self.tool(model=True)
        def read_file(name: str, ctx: Context) -> dict:
            """Read an uploaded file's contents by name."""
            return provider.on_read(name, ctx)

        @self.ui()
        def file_manager(ctx: Context) -> PrefabApp:

View on GitHub (pinned to 1f02114297)