pallets/flask · error · DebugFilesKeyError

You tried to access the file {key!r} in the request.files di

Error message

You tried to access the file {key!r} in the request.files dictionary but it does not exist. The mimetype for the request is {request.mimetype!r} instead of 'multipart/form-data' which means that no file contents were transmitted. To fix this error you should provide enctype="multipart/form-data" in your form.

The browser instead transmitted some file names. This was submitted: {names}

What it means

This is `DebugFilesKeyError`, raised in debug mode when your view accesses `request.files['key']` but the request was not sent as `multipart/form-data`. Flask (via `Request._load_form_data` in wrappers.py) patches the files multidict's `__getitem__` (`attach_enctype_error_multidict` in debughelpers.py) so that, when the key is missing from `files` but present in `form`, you get this explanatory error instead of a bare KeyError — the browser sent only the file *names* as text fields because the form lacked the right enctype.

Source

Thrown at src/flask/debughelpers.py:98

def attach_enctype_error_multidict(request: Request) -> None:
    """Patch ``request.files.__getitem__`` to raise a descriptive error
    about ``enctype=multipart/form-data``.

    :param request: The request to patch.
    :meta private:
    """
    oldcls = request.files.__class__

    class newcls(oldcls):  # type: ignore[valid-type, misc]
        def __getitem__(self, key: str) -> t.Any:
            try:
                return super().__getitem__(key)
            except KeyError as e:
                if key not in request.form:
                    raise

                raise DebugFilesKeyError(request, key).with_traceback(
                    e.__traceback__
                ) from None

    newcls.__name__ = oldcls.__name__
    newcls.__module__ = oldcls.__module__
    request.files.__class__ = newcls


def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]:
    yield f"class: {type(loader).__module__}.{type(loader).__name__}"
    for key, value in sorted(loader.__dict__.items()):
        if key.startswith("_"):
            continue
        if isinstance(value, (tuple, list)):
            if not all(isinstance(x, str) for x in value):
                continue
            yield f"{key}:"
            for item in value:

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Add `enctype="multipart/form-data"` to the HTML form (and use `method="post"`).
  2. If uploading via JavaScript, send a `FormData` object without manually setting Content-Type so the browser sets the multipart boundary.
  3. If using Python `requests`, pass the file via `files={'upload': fh}` rather than `data=`.
  4. In production-safe code, use `request.files.get('upload')` and handle the missing case explicitly.

Example fix

<!-- before -->
<form method="post">
  <input type="file" name="upload">
</form>
<!-- after -->
<form method="post" enctype="multipart/form-data">
  <input type="file" name="upload">
</form>
Defensive patterns

Strategy: validation

Validate before calling

# check before accessing request.files
if request.mimetype != 'multipart/form-data' or key not in request.files:
    abort(400, 'file upload missing or form lacked enctype=multipart/form-data')

Type guard

def has_uploaded_file(request, key: str) -> bool:
    return request.mimetype == 'multipart/form-data' and key in request.files

Prevention

When it happens

Trigger: A view does `request.files['upload']` on a POST from an HTML `<form>` without `enctype="multipart/form-data"`; the field name appears in `request.form` (as the filename string) but not in `request.files`, `app.debug` is True, and the request mimetype is `application/x-www-form-urlencoded`.

Common situations: Forgetting the enctype attribute on upload forms; sending uploads from JS/fetch or requests with default urlencoded/JSON encoding instead of FormData/multipart; API clients posting `files` under `data=` in Python `requests`.

Related errors


AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31). Data as JSON: /data/errors/43c4dabe9d7439ae.json. Report an issue: GitHub ↗.