QuantConnect/Lean · error · KeyError
No key found for either mapped or original key. Mapped Key:
Error message
No key found for either mapped or original key. Mapped Key: {mKey}; Original Key: {oKey} What it means
PandasMapper wraps pandas indexing functions (DataFrame.__getitem__, loc/xs/at, Index.get_loc) so Lean-created dataframes can be indexed by ticker or Symbol as well as by SID. wrap_keyerror_function first tries the mapped (SID-converted) key, then the original key; if both raise KeyError, it raises this consolidated KeyError listing both the mapped key and the original key attempted. It means neither the ticker/Symbol nor its SID form exists in the dataframe index.
Source
Thrown at Common/PandasMapper.py:93
newkwargs = kwargs
if len(args) > 1:
newargs = mapper(args)
if len(kwargs) > 0:
newkwargs = mapper(kwargs)
return f(*newargs, **newkwargs)
except KeyError as e:
pass
# Execute original
# Allows for df, Series, etc indexing for keys like 'SPY' if they exist
try:
return f(*args, **kwargs)
except KeyError as e:
mKey = [str(arg) for arg in newargs if isinstance(arg, str) or isinstance(arg, Symbol)]
oKey = [str(arg) for arg in args if isinstance(arg, str) or isinstance(arg, Symbol)]
raise KeyError(f"No key found for either mapped or original key. Mapped Key: {mKey}; Original Key: {oKey}")
wrapped_function.__name__ = f.__name__
return wrapped_function
def wrap_bool_function(f):
'''Wraps function f with wrapped_function, used for functions that reply true/false if key is found.
wrapped_function attempts with the original args, if its false, it converts the args / kwargs to use
alternative index keys and then attempts with the mapped args.
'''
def wrapped_function(*args, **kwargs):
# Try the original args; if true just return true
originalResult = f(*args, **kwargs)
if originalResult:
return originalResult
# Try our mapped args; return this result regardless
newargs = argsView on GitHub (pinned to d2c3659f87)
Solutions
- Confirm the symbol was actually included in the History request (df.index.get_level_values('symbol').unique()) before indexing.
- Ensure the security was added (AddEquity/AddData) so SymbolCache can map the ticker to the SID.
- Index by the canonical SID string str(symbol.id) or by the Symbol object you got from add_equity, not a freehand ticker.
- Guard with `'SPY' in df.index` (the wrapped __contains__ supports ticker/Symbol) before accessing.
Example fix
# before — index with a ticker not present in the history frame
history = self.history([self.spy, self.eur], 30, Resolution.DAILY)
apple = history.loc['AAPL'] # KeyError: No key found ... Mapped Key: ['AAPL']; Original Key: ['AAPL']
# after — verify membership and use the Symbol object you added
history = self.history([self.spy, self.eur], 30, Resolution.DAILY)
if str(self.spy.id) not in history.index.get_level_values('symbol').unique():
raise ValueError("SPY not in history result")
spy_rows = history.loc[str(self.spy.id)] Defensive patterns
Strategy: validation
Validate before calling
# Confirm the key form exists in the index before indexing
available = set(map(str, history.index.get_level_values(0)))
key = str(self.spy.id)
if key not in available and 'SPY' not in available:
raise ValueError(f"SPY not in history index; available: {sorted(available)}")
spy_rows = history.loc[key] Type guard
def key_in_history(history, symbol, ticker):
"""True when the history index contains the symbol's SID string or ticker."""
labels = set(map(str, history.index.get_level_values(0)))
return str(symbol.id) in labels or ticker in labels Try / catch
try:
rows = history.loc[str(self.spy.id)]
except KeyError:
available = sorted(set(map(str, history.index.get_level_values(0))))
self.debug(f"SPY not in history; index labels: {available}")
rows = None Prevention
- Add the security (AddEquity/AddData) before indexing history so SymbolCache can resolve the ticker to a SID.
- Index by str(symbol.id) or the Symbol object from add_*, not a freehand ticker.
- Use the wrapped 'ticker in df' membership test before accessing to avoid the consolidated KeyError.
When it happens
Trigger: You index a Lean history dataframe with a label that is not in the index under any supported form. E.g. df.loc['AAPL'] when the index only contains SPY/EUR rows; df[symbol] for a symbol never added; df.xs(str(symbol.id)) for a SID that was not part of the history request. The mapper tried the SID (via SymbolCache.try_get_symbol) and the raw key, found neither, and raised. This also fires if SymbolCache has no entry for the ticker so the mapped key equals the original and both miss.
Common situations: Indexing a multi-symbol history frame with a symbol/ticker that was not in the request. Using a ticker string before the security was AddEquity'd (SymbolCache empty). A typo in the ticker. Indexing after the dataframe was sliced/filtered so the label is gone. Custom data symbols whose SID string differs from what the caller used.
Related errors
- {symbols}, {symbol.id}, {symbol}, {ticker}. {e}
- History call failed: {e}
- Unexpected columns in SPY tick history
- Empty history data frame for {symbol}
- Could not unstack df. Columns: {', '.join(df.columns)} | {co
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/f041446e3146b70d.
Report an issue: GitHub.