langchain-ai/langgraph · error · ValueError

LANGGRAPH_AES_KEY environment variable is not set.

Error message

LANGGRAPH_AES_KEY environment variable is not set.

What it means

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.

Solutions

  1. Export the variable: export LANGGRAPH_AES_KEY=<16/24/32-byte key material>
  2. Or pass the key directly: EncryptedSerializer.from_pycryptodome_aes(key=b'...')
  3. Load the key from a secret manager and pass it explicitly instead of relying on the environment
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at libs/checkpoint/langgraph/checkpoint/serde/encrypted.py:56 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of langchain-ai/langgraph@38031739e5 (2026-08-26). Data as JSON: /api/errors/20a0a63e86f6dbef. Report an issue: GitHub.

Appendix: source

Thrown at libs/checkpoint/langgraph/checkpoint/serde/encrypted.py:56

    @classmethod
    def from_pycryptodome_aes(
        cls, serde: SerializerProtocol = JsonPlusSerializer(), **kwargs: Any
    ) -> "EncryptedSerializer":
        """Create an `EncryptedSerializer` using AES encryption."""
        try:
            from Crypto.Cipher import AES
        except ImportError:
            raise ImportError(
                "Pycryptodome is not installed. Please install it with `pip install pycryptodome`."
            ) from None

        # check if AES key is provided
        if "key" in kwargs:
            key: bytes = kwargs.pop("key")
        else:
            key_str = os.getenv("LANGGRAPH_AES_KEY")
            if key_str is None:
                raise ValueError("LANGGRAPH_AES_KEY environment variable is not set.")
            key = key_str.encode()
            if len(key) not in (16, 24, 32):
                raise ValueError("LANGGRAPH_AES_KEY must be 16, 24, or 32 bytes long.")

        # set default mode to EAX if not provided
        if kwargs.get("mode") is None:
            kwargs["mode"] = AES.MODE_EAX

        class PycryptodomeAesCipher(CipherProtocol):
            def encrypt(self, plaintext: bytes) -> tuple[str, bytes]:
                cipher = AES.new(key, **kwargs)
                ciphertext, tag = cipher.encrypt_and_digest(plaintext)
                return "aes", cipher.nonce + tag + ciphertext

            def decrypt(self, ciphername: str, ciphertext: bytes) -> bytes:
                assert ciphername == "aes", f"Unsupported cipher: {ciphername}"
                nonce = ciphertext[:16]
                tag = ciphertext[16:32]

View on GitHub (pinned to 38031739e5)