{"record":{"id":"20a0a63e86f6dbef","repo":"langchain-ai/langgraph","slug":"langgraph-aes-key-environment-variable-is-not-set","errorCode":null,"errorMessage":"LANGGRAPH_AES_KEY environment variable is not set.","messagePattern":"LANGGRAPH_AES_KEY environment variable is not set\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/checkpoint/langgraph/checkpoint/serde/encrypted.py","lineNumber":56,"sourceCode":"    @classmethod\n    def from_pycryptodome_aes(\n        cls, serde: SerializerProtocol = JsonPlusSerializer(), **kwargs: Any\n    ) -> \"EncryptedSerializer\":\n        \"\"\"Create an `EncryptedSerializer` using AES encryption.\"\"\"\n        try:\n            from Crypto.Cipher import AES\n        except ImportError:\n            raise ImportError(\n                \"Pycryptodome is not installed. Please install it with `pip install pycryptodome`.\"\n            ) from None\n\n        # check if AES key is provided\n        if \"key\" in kwargs:\n            key: bytes = kwargs.pop(\"key\")\n        else:\n            key_str = os.getenv(\"LANGGRAPH_AES_KEY\")\n            if key_str is None:\n                raise ValueError(\"LANGGRAPH_AES_KEY environment variable is not set.\")\n            key = key_str.encode()\n            if len(key) not in (16, 24, 32):\n                raise ValueError(\"LANGGRAPH_AES_KEY must be 16, 24, or 32 bytes long.\")\n\n        # set default mode to EAX if not provided\n        if kwargs.get(\"mode\") is None:\n            kwargs[\"mode\"] = AES.MODE_EAX\n\n        class PycryptodomeAesCipher(CipherProtocol):\n            def encrypt(self, plaintext: bytes) -> tuple[str, bytes]:\n                cipher = AES.new(key, **kwargs)\n                ciphertext, tag = cipher.encrypt_and_digest(plaintext)\n                return \"aes\", cipher.nonce + tag + ciphertext\n\n            def decrypt(self, ciphername: str, ciphertext: bytes) -> bytes:\n                assert ciphername == \"aes\", f\"Unsupported cipher: {ciphername}\"\n                nonce = ciphertext[:16]\n                tag = ciphertext[16:32]","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/langchain-ai/langgraph/blob/38031739e551638e373fb553453256c23feeb41f/libs/checkpoint/langgraph/checkpoint/serde/encrypted.py#L38-L74","documentation":"Configuration guard in EncryptedSerializer.from_pycryptodome_aes: no 'key' keyword was supplied and the fallback environment variable LANGGRAPH_AES_KEY is unset (os.getenv returned None), so there is no AES key material to derive the cipher. The input at fault is the missing key configuration, not the environment or code.","triggerScenarios":"Thrown at libs/checkpoint/langgraph/checkpoint/serde/encrypted.py:56 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Export the variable: export LANGGRAPH_AES_KEY=<16/24/32-byte key material>","Or pass the key directly: EncryptedSerializer.from_pycryptodome_aes(key=b'...')","Load the key from a secret manager and pass it explicitly instead of relying on the environment"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"38031739e551638e373fb553453256c23feeb41f","analyzedAt":"2026-08-26T18:02:49.312Z","contentChangedAt":"2026-08-26T18:02:49.312Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}