ValueError: The feature names should match those that were passed in Scikit-Learn
Ensure test DataFrames have the exact same column names and ordering as the training data, or pass raw NumPy arrays (X.values) to bypass name checks.
Root Cause Analysis
This error occurs when Python tries to run inference (model.predict(), model.transform(), or model.predict_proba()) on a scikit-learn estimator that was fitted on a pandas DataFrame with named columns, but the evaluation data has different column names, missing columns, or a different column order.
1. Feature Name Validation in Modern Scikit-Learn
Since Scikit-Learn 1.0+, estimators automatically store the feature names seen during fit() in the feature_names_in_ attribute. When calling predict(), the estimator strictly validates that input DataFrame column names match feature_names_in_ item-for-item.
2. Renamed or Reordered Columns in Test Sets
If the training DataFrame contained ['age', 'income'] and the inference DataFrame has ['income', 'age'] or renamed columns ['years', 'salary'], Scikit-Learn raises ValueError: The feature names should match those that were passed during fit.
3. Passing DataFrame vs NumPy Array Discrepancy
Fitting on a pandas DataFrame (fit(df, y)) sets model.feature_names_in_. If you subsequently pass a DataFrame with different column names, validation fails. If you pass an unadorned NumPy array, scikit-learn issues a warning or error depending on dimension match.
4. Pipeline Preprocessing Alterations
Custom transformers or ColumnTransformer steps that rename or drop columns without updating feature name metadata can cause downstream estimators to fail.
Reproduction Code (MCVE)
import pandas as pd
from sklearn.linear_model import LinearRegression
# Fit model on DataFrame with specific feature names
X_train = pd.DataFrame({'age': [25, 30, 35], 'income': [50000, 60000, 75000]})
y_train = [1, 2, 3]
model = LinearRegression().fit(X_train, y_train)
# Predict with mismatched column names raises ValueError
X_test = pd.DataFrame({'years': [28, 40], 'salary': [55000, 80000]})
model.predict(X_test)
Solution 1: Align Feature Names and Order with Training Schema
Ensure inference DataFrames match the exact column names and order stored in model.feature_names_in_.
import pandas as pd
from sklearn.linear_model import LinearRegression
X_train = pd.DataFrame({'age': [25, 30, 35], 'income': [50000, 60000, 75000]})
y_train = [1, 2, 3]
model = LinearRegression().fit(X_train, y_train)
# Match exact column names
X_test = pd.DataFrame({'age': [28, 40], 'income': [55000, 80000]})
predictions = model.predict(X_test)
print(f'Predictions generated: {predictions}')
Solution 2: Pass Raw NumPy Arrays to Bypass Name Validation
Extract underlying array values (X.values) if column schemas vary dynamically between training and serving environments.
import pandas as pd
from sklearn.linear_model import LinearRegression
X_train = pd.DataFrame({'age': [25, 30, 35], 'income': [50000, 60000, 75000]})
y_train = [1, 2, 3]
# Fit on raw array values
model = LinearRegression().fit(X_train.values, y_train)
# Predict using raw array
X_test_raw = [[28, 55000], [40, 80000]]
predictions = model.predict(X_test_raw)
print(f'Predictions from raw array: {predictions}')
A common mistake is assuming that scikit-learn models match features by position rather than name when given DataFrames. If X_test has the same column names but in reversed order (e.g. ['income', 'age']), scikit-learn will raise an error or reorder features silently. Always align columns explicitly using X_test = X_test[model.feature_names_in_]. Edge cases occur with single-sample inference (e.g. predicting a single row from a dictionary in a FastAPI endpoint). Convert the dict to pd.DataFrame([payload])[model.feature_names_in_] to guarantee exact shape and column ordering. Contrast this error with ValueError: Found array with dim 3. Estimator expected <= 2, which occurs when input data has invalid rank.