pallets/flask · warning · DebugFilesKeyError
You tried to access the file
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. What it means
attach_enctype_error_multidict (debug mode only) patches request.files.__getitem__ to raise DebugFilesKeyError when a missing file key IS present in request.form. This means the field name was submitted as a form value, not as a file upload—almost always because the HTML form lacks enctype="multipart/form-data", so the browser sent the field as text and request.mimetype is not multipart/form-data.
Solutions
- Add enctype="multipart/form-data" to the <form> element: <form method="post" enctype="multipart/form-data">.
- If uploading via fetch/axios, send a FormData object so the browser sets the correct multipart Content-Type (do not set Content-Type manually).
- Use request.files.get('upload') with a None check, and validate request.mimetype == 'multipart/form-data' for a clearer non-debug error.
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
def is_multipart_upload(request) -> bool:
return request.mimetype == 'multipart/form-data'
# in the view before accessing files
if not is_multipart_upload(request):
return 'Form must use enctype=multipart/form-data', 400 Type guard
def is_multipart(request) -> bool:
return request.mimetype == 'multipart/form-data' Try / catch
from flask import request
try:
f = request.files['upload']
except KeyError:
if request.mimetype != 'multipart/form-data':
return 'Missing enctype=multipart/form-data', 400
raise Prevention
- Always set enctype="multipart/form-data" on forms with file inputs.
- Validate request.mimetype before reading request.files in upload views.
When it happens
Trigger: In debug mode, a view does request.files['upload'] but the form tag has no enctype attribute (defaults to application/x-www-form-urlencoded). The key exists in request.form (the filename string) but not in request.files, triggering the patched KeyError with the descriptive mimetype message. Only attaches when app.debug is True.
Common situations: File upload form missing enctype. Switching a form to handle uploads but forgetting the enctype attribute. AJAX upload sending the wrong Content-Type header. Using a FormData object incorrectly client-side.
Related errors
- A request was sent to
- ' ' is not a recognized HTTP error code. Use a subclass of…
- A valid Flask application was not obtained from
- 'after_this_request' can only be used when a request…
- Allowed methods must be a list of strings, for example…
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/b432baa05520c09e.
Report an issue: GitHub.
Appendix: 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 3596b1ab61)