Hidden Assumptions in scikit-learn
12 assumptions this code never checks · 4 critical · spanning Scale, Domain, Resource, Shape, Ordering, Temporal, Environment, Contract
Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at scikit-learn/scikit-learn and picked out the few most likely to cause trouble. The full list is just below.
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
If dimensions approach or exceed 30, the function relies on numpy's ability to generate 2^30 (≈1 billion) random samples, potentially causing memory exhaustion or integer overflow on 32-bit systems
If OpenML changes their API schema or returns different data structures, the function will fail with KeyError or AttributeError when accessing expected dictionary keys, breaking all dataset downloads
Large datasets (multi-GB) can fill up disk space causing silent failures or corrupted cache files, with no cleanup mechanism when downloads are interrupted
Show everything (9 more)
Assumes input data has the same number of features as the data used during fit(), but only validates this through array shape checking in parent classes
If this fails: If input has different number of features, transform() will either crash with indexing errors or silently use wrong bin edges for features, producing incorrect discretized values
sklearn/preprocessing/_discretization.py:KBinsDiscretizer.transform
When strategy='quantile', assumes input data maintains the same statistical distribution as training data, particularly the quantile boundaries learned during fit()
If this fails: If new data has a completely different distribution (e.g., all values outside the original range), quantile-based binning will assign all samples to edge bins, losing the intended uniform sample distribution across bins
sklearn/preprocessing/_discretization.py:KBinsDiscretizer
Box-Cox transformation assumes all input values are strictly positive (> 0), while Yeo-Johnson allows negative values, but this constraint is not validated in the preprocessing pipeline
If this fails: Applying Box-Cox to data containing zero or negative values will produce NaN or infinite results, silently corrupting the transformed dataset without raising an error
examples/preprocessing/plot_map_data_to_normal.py
Assumes feature variances are non-zero during fit() - if a feature has zero variance, the computed std will be 0 and division by std during transform will produce infinite values
If this fails: Features with constant values (zero variance) will produce infinite or NaN values after standardization, corrupting the transformed data matrix and causing downstream models to fail
sklearn/preprocessing/_data.py:StandardScaler
Assumes cached dataset files remain valid indefinitely once downloaded, with no mechanism to check if remote datasets have been updated or if cache integrity is maintained
If this fails: Users may work with stale or corrupted cached data without knowing it, leading to inconsistent results when the same dataset ID returns different data over time
sklearn/datasets/_openml.py:_get_local_path
Assumes stable internet connectivity and that OpenML servers (api.openml.org) are accessible, with basic urllib timeout handling but no retry logic for transient failures
If this fails: Network interruptions or temporary server outages cause immediate failure of dataset loading, forcing users to restart entire workflows even for brief connectivity issues
sklearn/datasets/_openml.py:urlopen
When encode='onehot', assumes downstream estimators can handle the increased dimensionality from n_features to n_features × n_bins, but provides no warning about this expansion
If this fails: Memory usage can explode unexpectedly (e.g., 100 features with 10 bins each becomes 1000 features), causing out-of-memory errors in downstream processing that seem unrelated to the discretization step
sklearn/preprocessing/_discretization.py:KBinsDiscretizer
When strategy='kmeans', assumes the k-means clustering will converge to meaningful centroids for bin boundaries, but doesn't validate convergence or handle degenerate cases
If this fails: For pathological data distributions (e.g., all values identical), k-means may not converge or create duplicate bin edges, resulting in fewer bins than requested without user notification
sklearn/preprocessing/_discretization.py:KBinsDiscretizer
Example assumes memory capacity to handle 50,000 samples for demonstrating cross-fitting, but doesn't scale the example based on available system resources
If this fails: On memory-constrained systems, the example may fail with out-of-memory errors, making it impossible to run the demonstration of cross-fitting behavior
examples/preprocessing/plot_target_encoder_cross_val.py:n_samples=50_000
See the full structural analysis of scikit-learn: the pipeline, data models, and system behavior that put these assumptions in context.
Full analysis of scikit-learn/scikit-learn →Compare scikit-learn
Frequently Asked Questions
What does scikit-learn assume that could break in production?
The one most likely to cause trouble: Assumes dataset dimensions won't exceed 30 in the recursive base case, with hardcoded split at dimension 30 using 2^30 as the sample space size If this fails, If dimensions approach or exceed 30, the function relies on numpy's ability to generate 2^30 (≈1 billion) random samples, potentially causing memory exhaustion or integer overflow on 32-bit systems
How many hidden assumptions does scikit-learn have?
CodeSea found 12 assumptions scikit-learn relies on but never validates, 4 of them critical, spanning Scale, Domain, Resource, Shape, Ordering, Temporal, Environment, Contract. Most are routine — the analysis flags the two or three most likely to actually bite.
What is a hidden assumption?
Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.