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".

Worth your attention first

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

Worth your attention first

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

Worth your attention first

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)
Shape

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
Ordering

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
Domain

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
Scale

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
Temporal

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
Environment

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
Contract

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
Domain

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
Scale

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.