[BUG] .ipynb notebook artifacts are served as application/octet-stream instead of text/plain
[!WARNING] Before submitting a PR, please make sure that:
- A maintainer has triaged this issue and applied the
readylabel- This issue has no assignee
- No duplicate PR exists
PRs not meeting these requirements may be automatically closed.
Issues Policy acknowledgement
- I have read and agree to submit bug reports in accordance with the issues policy
Where did you encounter this bug?
Local machine
MLflow version
- Client: 3.x.y
- Tracking server: 3.x.y
System information
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): Ubuntu 22.04 / Windows 11 (reproducible on any OS)
- Python version: 3.10+
Describe the problem
Jupyter notebook (.ipynb) files logged as MLflow artifacts are always served with Content-Type: application/octet-stream, even though .ipynb files are plain-text JSON. This forces the browser to download the file instead of allowing the tracking server UI (or any client relying on the artifact's mime type) to preview/render it inline like other text-based artifacts (.py, .json, .md, .yaml, etc.).
Root cause: mlflow/utils/mime_type_utils.py's _guess_mime_type() first checks a hardcoded get_text_extensions() allowlist, then falls back to Python's stdlib mimetypes.guess_type(). Neither path recognizes .ipynb:
.ipynb is not present in get_text_extensions(). mimetypes.guess_type("notebook.ipynb") returns (None, None) since .ipynb is not a registered MIME type in the stdlib.
As a result, _guess_mime_type() falls through to the binary fallback and returns application/octet-stream.
Expected behavior: .ipynb files should be detected as text/plain (or application/x-ipynb+json) and be viewable in the artifact browser, consistent with how .py, .json, and .md files are handled.
Actual behavior: .ipynb files are always treated as opaque binary and force a download in the UI / artifact viewer instead of rendering inline.
Tracking information
Not applicable - this is a static mime-type detection bug, not run-specific.
Code to reproduce issue
from mlflow.utils.mime_type_utils import _guess_mime_type
print(_guess_mime_type("notebook.ipynb"))
Actual: application/octet-stream
Expected: text/plain
Stack trace
N/A - this is a behavioral/logic bug, not a crash. No exception is raised.
Other info / logs
import mlflow
with mlflow.start_run(): mlflow.log_artifact("notebook.ipynb")
Willingness to contribute
Yes. I can contribute a fix for this bug independently.
What component(s) does this bug affect?
-
area/tracking: Tracking Service, tracking client APIs, autologging -
area/model-registry: Model Registry service, APIs, and the fluent client calls for Model Registry -
area/scoring: MLflow model serving, deployment tools, Spark UDFs -
area/evaluation: MLflow model evaluation features, evaluation metrics, and evaluation workflows -
area/prompt: MLflow prompt engineering features, prompt templates, and prompt management -
area/tracing: MLflow Tracing features, tracing APIs, and LLM tracing functionality -
area/gateway: MLflow AI Gateway client APIs, server, and third-party integrations -
area/projects: MLproject format, project running backends -
area/uiux: Front-end, user experience, plotting -
area/docs: MLflow documentation pages
Source: mlflow/mlflow