QuantConnect/Lean · error · AssertionError
Unexpected columns in SPY tick history
Error message
Unexpected columns in SPY tick history
What it means
Regression assertion that the SPY tick history dataframe has exactly the expected column set: askprice, asksize, bidprice, bidsize, exchange, lastprice, quantity. It uses np.array_equal against the sorted columns, so both the names and the exact set must match. The assertion fires if Lean's PandasData column layout for Tick data changed or columns were added/renamed/missing.
Source
Thrown at Algorithm.Python/PandasDataFrameFromMultipleTickTypeTickHistoryRegressionAlgorithm.py:42
self.set_end_date(2013, 10, 8)
spy = self.add_equity("SPY", Resolution.MINUTE).symbol
subscriptions = [x for x in self.subscription_manager.subscriptions if x.symbol == spy]
if len(subscriptions) != 2:
raise AssertionError(f"Expected 2 subscriptions, but found {len(subscriptions)}")
history = pd.DataFrame()
try:
history = self.history(Tick, spy, timedelta(days=1), Resolution.TICK)
except Exception as e:
raise AssertionError(f"History call failed: {e}")
if history.shape[0] == 0:
raise AssertionError("SPY tick history is empty")
if not np.array_equal(history.columns.to_numpy(), ['askprice', 'asksize', 'bidprice', 'bidsize', 'exchange', 'lastprice', 'quantity']):
raise AssertionError("Unexpected columns in SPY tick history")
self.quit()
View on GitHub (pinned to d2c3659f87)
Solutions
- Log the actual columns (list(history.columns)) to see which name differs.
- If a column was renamed/added on purpose in a Lean change, update the expected array to match the new contract.
- If the frame shape is wrong (e.g. Series), ensure the request returns a DataFrame — request a single symbol but keep the multi-index path, or inspect dtype.
- Align the pandas version with what the dataframe builder expects.
Example fix
# before
if not np.array_equal(history.columns.to_numpy(), ['askprice','asksize','bidprice','bidsize','exchange','lastprice','quantity']):
raise AssertionError("Unexpected columns in SPY tick history")
# after (report the diff so the mismatch is obvious)
expected = ['askprice','asksize','bidprice','bidsize','exchange','lastprice','quantity']
actual = sorted(history.columns.astype(str).tolist())
if sorted(expected) != actual:
raise AssertionError(f"Unexpected columns in SPY tick history: {actual}") Defensive patterns
Strategy: validation
Validate before calling
# Compare as sorted sets and report the diff
import numpy as np
expected = ['askprice','asksize','bidprice','bidsize','exchange','lastprice','quantity']
actual = sorted(map(str, history.columns))
if sorted(expected) != actual:
self.debug(f"Column mismatch. expected={expected} actual={actual}") Type guard
def columns_match(history, expected):
"""True when the frame columns equal the expected set (order-insensitive)."""
return set(map(str, history.columns)) == set(expected) Prevention
- After a Lean/pandas upgrade, re-derive the expected tick columns from the actual frame.
- Compare columns as sets to avoid ordering brittleness.
- Log the actual columns when the assertion fires to localize added/renamed fields.
When it happens
Trigger: history.columns.to_numpy() does not equal the expected 7-name array. This happens after a change to the Tick property/column mapping in PandasData (e.g. a column renamed, a new field added like 'suspectedfalsy', or a column dropped), or when the returned frame is a different shape (e.g. transposed, or a Series instead of a DataFrame).
Common situations: Lean contributors hit this after modifying PandasData.GetFrame / the Tick data column generation, or after a refactor of the BaseData-to-pandas column mapping. Users hit it after upgrading Lean if the tick column contract changed, or when the history call unexpectedly returns a different dtype/layout (e.g. due to a pandas version difference).
Related errors
- History call failed: {e}
- Expected 2 subscriptions, but found {len(subscriptions)}
- SPY tick history is empty
- Could not unstack df. Columns: {', '.join(df.columns)} | {co
- Empty history data frame for {symbol}
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/4a33d6fafdbcfc4e.
Report an issue: GitHub.