{"record":{"id":"f041446e3146b70d","repo":"QuantConnect/Lean","slug":"no-key-found-for-either-mapped-or-original-key-ma","errorCode":null,"errorMessage":"No key found for either mapped or original key. Mapped Key: {mKey}; Original Key: {oKey}","messagePattern":"No key found for either mapped or original key\\. Mapped Key: (.+?); Original Key: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"Common/PandasMapper.py","lineNumber":93,"sourceCode":"            newkwargs = kwargs\n\n            if len(args) > 1:\n                newargs = mapper(args)\n            if len(kwargs) > 0:\n                newkwargs = mapper(kwargs)\n\n            return f(*newargs, **newkwargs)\n        except KeyError as e:\n            pass\n\n        # Execute original\n        # Allows for df, Series, etc indexing for keys like 'SPY' if they exist\n        try:\n            return f(*args, **kwargs)\n        except KeyError as e:\n            mKey = [str(arg) for arg in newargs if isinstance(arg, str) or isinstance(arg, Symbol)]\n            oKey = [str(arg) for arg in args if isinstance(arg, str) or isinstance(arg, Symbol)]\n            raise KeyError(f\"No key found for either mapped or original key. Mapped Key: {mKey}; Original Key: {oKey}\")\n\n    wrapped_function.__name__ = f.__name__\n    return wrapped_function\n\ndef wrap_bool_function(f):\n    '''Wraps function f with wrapped_function, used for functions that reply true/false if key is found.\n    wrapped_function attempts with the original args, if its false, it converts the args / kwargs to use\n    alternative index keys and then attempts with the mapped args.\n    '''\n    def wrapped_function(*args, **kwargs):\n\n        # Try the original args; if true just return true\n        originalResult = f(*args, **kwargs)\n        if originalResult:\n            return originalResult\n\n        # Try our mapped args; return this result regardless\n        newargs = args","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Common/PandasMapper.py#L75-L111","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before — index with a ticker not present in the history frame\nhistory = self.history([self.spy, self.eur], 30, Resolution.DAILY)\napple = history.loc['AAPL']  # KeyError: No key found ... Mapped Key: ['AAPL']; Original Key: ['AAPL']\n\n# after — verify membership and use the Symbol object you added\nhistory = self.history([self.spy, self.eur], 30, Resolution.DAILY)\nif str(self.spy.id) not in history.index.get_level_values('symbol').unique():\n    raise ValueError(\"SPY not in history result\")\nspy_rows = history.loc[str(self.spy.id)]","handlingStrategy":"validation","validationCode":"# Confirm the key form exists in the index before indexing\navailable = set(map(str, history.index.get_level_values(0)))\nkey = str(self.spy.id)\nif key not in available and 'SPY' not in available:\n    raise ValueError(f\"SPY not in history index; available: {sorted(available)}\")\nspy_rows = history.loc[key]","typeGuard":"def key_in_history(history, symbol, ticker):\n    \"\"\"True when the history index contains the symbol's SID string or ticker.\"\"\"\n    labels = set(map(str, history.index.get_level_values(0)))\n    return str(symbol.id) in labels or ticker in labels","tryCatchPattern":"try:\n    rows = history.loc[str(self.spy.id)]\nexcept KeyError:\n    available = sorted(set(map(str, history.index.get_level_values(0))))\n    self.debug(f\"SPY not in history; index labels: {available}\")\n    rows = None","preventionTips":["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."],"tags":["quantconnect","lean","pandas","indexing","symbol-cache","key-error","python"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}