{"record":{"id":"5171597288a7892b","repo":"langchain-ai/langchain","slug":"missing-keys-sorted-missing-keys-in-config-con","errorCode":null,"errorMessage":"Missing keys {sorted(missing_keys)} in config['configurable'] Expected keys are {sorted(expected_keys)}.When using via .invoke() or .stream(), pass in a config; e.g., chain.invoke({example_input}, {example_config})","messagePattern":"Missing keys (.+?) in config\\['configurable'\\] Expected keys are (.+?)\\.When using via \\.invoke\\(\\) or \\.stream\\(\\), pass in a config; e\\.g\\., chain\\.invoke\\((.+?), (.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/history.py","lineNumber":600,"sourceCode":"        config = super()._merge_configs(*configs)\n        expected_keys = [field_spec.id for field_spec in self.history_factory_config]\n\n        configurable = config.get(\"configurable\", {})\n\n        missing_keys = set(expected_keys) - set(configurable.keys())\n        parameter_names = _get_parameter_names(self.get_session_history)\n\n        if missing_keys and parameter_names:\n            example_input = {self.input_messages_key: \"foo\"}\n            example_configurable = dict.fromkeys(missing_keys, \"[your-value-here]\")\n            example_config = {\"configurable\": example_configurable}\n            msg = (\n                f\"Missing keys {sorted(missing_keys)} in config['configurable'] \"\n                f\"Expected keys are {sorted(expected_keys)}.\"\n                f\"When using via .invoke() or .stream(), pass in a config; \"\n                f\"e.g., chain.invoke({example_input}, {example_config})\"\n            )\n            raise ValueError(msg)\n\n        if len(expected_keys) == 1:\n            if parameter_names:\n                # If arity = 1, then invoke function by positional arguments\n                message_history = self.get_session_history(\n                    configurable[expected_keys[0]]\n                )\n            else:\n                if not config:\n                    config[\"configurable\"] = {}\n                message_history = self.get_session_history()\n        else:\n            # otherwise verify that names of keys patch and invoke by named arguments\n            if set(expected_keys) != set(parameter_names):\n                msg = (\n                    f\"Expected keys {sorted(expected_keys)} do not match parameter \"\n                    f\"names {sorted(parameter_names)} of get_session_history.\"\n                )","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/history.py#L582-L618","documentation":"RunnableWithMessageHistory derives session-scoped history by calling your get_session_history callable with keys from config['configurable']. Before invoking, it computes which expected keys are missing from the configurable dict; any missing key (with a parameterized callable) raises this ValueError, complete with an example of how to pass config to .invoke()/.stream().","triggerScenarios":"Calling wrapped.invoke(input) or .stream() without {\"configurable\": {\"session_id\": \"...\"}} (or without whichever keys get_session_history declares, e.g. user_id when using history_factory_config).","commonSituations":"Forgetting the config argument; passing config=None; renaming configurable keys so they no longer match the factory signature; async paths (.ainvoke) hitting the same merge.","solutions":["Pass the session config: wrapped.invoke(input, {\"configurable\": {\"session_id\": \"<id>\"}})","If get_session_history takes multiple params, supply all declared keys in configurable (match history_factory_config field ids)","Double-check spelling: the key must equal the parameter name / field_spec.id exactly"],"exampleFix":"# before\nwrapped.invoke({\"question\": \"hi\"})  # ValueError\n# after\nwrapped.invoke(\n    {\"question\": \"hi\"}, {\"configurable\": {\"session_id\": \"abc123\"}},\n)","handlingStrategy":"validation","validationCode":"cfg = {\"configurable\": {\"session_id\": \"abc\"}}\nmissing = {\"session_id\"} - set(cfg[\"configurable\"])\nassert not missing, f\"pass configurable with {missing}\"","typeGuard":null,"tryCatchPattern":"try:\n    wrapped.invoke(x, cfg)\nexcept ValueError as e:\n    if \"Missing keys\" in str(e):\n        wrapped.invoke(x, {\"configurable\": {\"session_id\": new_session_id()}})","preventionTips":["Standardize a helper make_config(session_id) used for every history-wrapped call","Never call .invoke()/.stream() on these wrappers without a configurable dict"],"tags":["runnable","message-history","config","session-id","valueerror"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}