`xp.isdtype` checks raise on NumPy `StringDType`
[!WARNING] This issue is not yet ready for a PR. If you are interested in contributing to scikit-learn, please have a look at our contributing guidelines, and in particular the sections for new contributors and the "Needs triage" label.
Describe the bug and give evidence about its user-facing impact
numpy.dtypes.StringDType (and other new-style DType classes) crash xp.isdtype() across many sklearn utilities.
numpy's (and array-api-compat's) isdtype() raises TypeError instead of returning False for numpy's new-style DType classes. sklearn calls xp.isdtype(...) in many places expecting False for unrecognized dtypes, not a crash.
Steps/Code to Reproduce
import numpy as np
np.isdtype(np.dtypes.StringDType(), "numeric")
# TypeError: dtype argument must be a NumPy dtype, but it is a <class 'numpy.dtypes.StringDType'>.
from sklearn.utils.multiclass import type_of_target
type_of_target(np.array(["a", "b", "a"], dtype=np.dtypes.StringDType()))
# TypeError: dtype argument must be a NumPy dtype, but it is a <class 'numpy.dtypes.StringDType'>.
Confirmed crash sites (14), all via xp.isdtype() except unique_labels:
| Function | File |
|---|---|
check_array (any dtype=, incl. None) |
utils/validation.py |
type_of_target |
utils/multiclass.py |
_is_integral_float |
utils/multiclass.py |
_assert_all_finite |
utils/validation.py |
_randomized_range_finder |
utils/extmath.py |
_safe_accumulator_op |
utils/extmath.py |
_find_matching_floating_dtype |
utils/_array_api.py |
_average |
utils/_array_api.py |
label_binarize |
preprocessing/_label.py |
LabelBinarizer.inverse_transform |
preprocessing/_label.py |
RidgeClassifier.fit |
linear_model/_ridge.py |
_encode |
utils/_encode.py |
_check_unknown (→ OrdinalEncoder.fit_transform) |
utils/_encode.py |
unique_labels (np.dtype(y.dtype, metadata=...)) |
utils/_unique.py |
Not affected: is_multilabel, LabelEncoder.fit, _array_indexing, _determine_key_type.
Related: #34383 (motivation — proposes StringDType internally in encoders), #9777 (same failure pattern, closed).
Expected Results
Unrecognized dtypes should be treated like any other unsupported dtype (e.g. return False/"unknown"), not raise.
Actual Results
TypeError at every site listed above (unique_labels raises via a different call, same root cause).
Versions
Python 3.11.15
scikit-learn 1.8.0 and 1.9.1 (both confirmed broken)
numpy 2.4.4
pandas 3.0.2
polars 1.44.0
Interest in fixing the bug
One internal helper, e.g. _safe_isdtype(), wrapping xp.isdtype() to catch TypeError and return False, used at all sites above instead of patching each individually.
Source: scikit-learn/scikit-learn