Breaking change on minor version of langgraph-checkpoint-postgres after 2.0.21 #909

Closed
opened 2026-02-20 17:42:19 -05:00 by yindo · 2 comments
Owner

Originally created by @olixis on GitHub (Aug 8, 2025).

Checked other resources

  • This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/).
  • I added a clear and detailed title that summarizes the issue.
  • I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
  • I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.

Example Code

import os
import sys
import importlib.metadata as ilmd

from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.checkpoint.base import empty_checkpoint
from langchain_core.messages import HumanMessage


PG_URI = os.environ.get(
    "PG_URI",
    "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable",
)


def main() -> None:
    version = ilmd.version("langgraph-checkpoint-postgres")
    print(f"langgraph-checkpoint-postgres=={version}")
    print(f"PG_URI={PG_URI}")

    # Minimal config + empty checkpoint
    config = {"configurable": {"thread_id": "thread-mre", "checkpoint_ns": ""}}
    checkpoint = empty_checkpoint()

    # Non-JSON object inside metadata (works on 2.0.21 via JsonPlus, fails on 2.0.22+)
    metadata = {
        "source": "input",
        "step": 1,
        "writes": {},
        "message": HumanMessage(content="hello world"),
    }

    with PostgresSaver.from_conn_string(PG_URI) as saver:
        saver.setup()
        saver.put(config, checkpoint, metadata, {})
        print("Saved checkpoint OK (unexpected on 2.0.22+)")


if __name__ == "__main__":
    try:
        main()
    except Exception as exc:  # noqa: BLE001 - explicit for MRE visibility
        print("Raised:", repr(exc))
        # re-raise for full traceback in CI/issue
        raise

Error Message and Stack Trace (if applicable)

redacted Object of type HumanMessage is not JSON serializable') redacted

Description

Summary

Upgrading langgraph-checkpoint-postgres from 2.0.21 to 2.0.22 breaks metadata serialization. Code that saved checkpoints with non‑JSON objects in metadata (e.g., HumanMessage) now raises “Object of type HumanMessage is not JSON serializable.”

What I’m doing

Saving a checkpoint with PostgresSaver.put(...) where the metadata includes a LangChain HumanMessage.

Expected behavior

  • Same behavior as 2.0.21: metadata accepted (JsonPlus previously handled complex Python objects), or clear migration guidance if behavior is intentionally changed.

Actual behavior

  • On 2.0.22, calling put(...) raises:
    • Exception: “Object of type HumanMessage is not JSON serializable”

Minimal reproducible example

import os
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.checkpoint.base import empty_checkpoint
from langchain_core.messages import HumanMessage

PG_URI = os.getenv(
    "PG_URI",
    "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable",
)

config = {"configurable": {"thread_id": "thread-mre", "checkpoint_ns": ""}}
checkpoint = empty_checkpoint()
metadata = {
    "source": "input",
    "step": 1,
    "writes": {},
    "message": HumanMessage(content="hello world"),  # non-JSON object
}

with PostgresSaver.from_conn_string(PG_URI) as saver:
    saver.setup()
    saver.put(config, checkpoint, metadata, {})  # 2.0.22 -> raises; 2.0.21 -> OK

Environment

  • Works: langgraph-checkpoint-postgres==2.0.21
  • Fails: langgraph-checkpoint-postgres==2.0.22
  • Python 3.10+/3.11
  • psycopg 3 (binary/pool)
  • OS: Linux
  • Postgres: local instance

Additional notes

  • In 2.0.21, metadata was serialized via JsonPlus (tolerated Python objects).
  • In 2.0.22, metadata is passed directly as JSONB (Jsonb(get_checkpoint_metadata(...))), which rejects non‑JSON objects.
  • If this change is intended, please document it and provide a migration note (e.g., require JSON-only metadata or recommend moving complex objects to channel blobs).

System Info

System Information

OS: Linux
OS Version: #27~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 17:38:49 UTC 2
Python Version: 3.11.12 (main, May 22 2025, 15:29:00) [GCC 13.3.0]

Package Information

langchain_core: 0.2.43
langchain: 0.2.17
langchain_community: 0.2.19
langsmith: 0.1.147
langchain_google_calendar_tools: 0.0.1
langchain_openai: 0.1.25
langchain_postgres: 0.0.12
langchain_text_splitters: 0.2.4
langchainhub: 0.1.21
langgraph: 0.2.76

Optional packages not installed

langserve

Other Dependencies

aiohttp: 3.12.14
async-timeout: 5.0.1
dataclasses-json: 0.6.7
google-api-python-client>=2.104.0: Installed. No version info available.
google-auth-oauthlib>=1.1.0: Installed. No version info available.
httpx: 0.28.1
jsonpatch: 1.33
langchain>=0.0.335: Installed. No version info available.
langgraph-checkpoint: 2.1.1
langgraph-sdk: 0.1.74
langsmith-pyo3: Installed. No version info available.
numpy: 1.26.4
openai: 1.97.1
orjson: 3.11.0
packaging: 24.2
pgvector: 0.2.5
protobuf>=4.25.0: Installed. No version info available.
psycopg: 3.2.1
psycopg-pool: 3.2.2
pydantic: 2.8.2
pytz>=2023.3.post1: Installed. No version info available.
PyYAML: 6.0.2
requests: 2.32.3
requests-toolbelt: 1.0.0
SQLAlchemy: 2.0.41
sqlalchemy: 2.0.41
tenacity: 8.5.0
tiktoken: 0.9.0
types-requests: 2.32.4.20250611
typing-extensions: 4.14.1

Originally created by @olixis on GitHub (Aug 8, 2025). ### Checked other resources - [x] This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/). - [x] I added a clear and detailed title that summarizes the issue. - [x] I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example). - [x] I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue. ### Example Code ```python import os import sys import importlib.metadata as ilmd from langgraph.checkpoint.postgres import PostgresSaver from langgraph.checkpoint.base import empty_checkpoint from langchain_core.messages import HumanMessage PG_URI = os.environ.get( "PG_URI", "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable", ) def main() -> None: version = ilmd.version("langgraph-checkpoint-postgres") print(f"langgraph-checkpoint-postgres=={version}") print(f"PG_URI={PG_URI}") # Minimal config + empty checkpoint config = {"configurable": {"thread_id": "thread-mre", "checkpoint_ns": ""}} checkpoint = empty_checkpoint() # Non-JSON object inside metadata (works on 2.0.21 via JsonPlus, fails on 2.0.22+) metadata = { "source": "input", "step": 1, "writes": {}, "message": HumanMessage(content="hello world"), } with PostgresSaver.from_conn_string(PG_URI) as saver: saver.setup() saver.put(config, checkpoint, metadata, {}) print("Saved checkpoint OK (unexpected on 2.0.22+)") if __name__ == "__main__": try: main() except Exception as exc: # noqa: BLE001 - explicit for MRE visibility print("Raised:", repr(exc)) # re-raise for full traceback in CI/issue raise ``` ### Error Message and Stack Trace (if applicable) ```shell redacted Object of type HumanMessage is not JSON serializable') redacted ``` ### Description ### Summary Upgrading `langgraph-checkpoint-postgres` from 2.0.21 to 2.0.22 breaks metadata serialization. Code that saved checkpoints with non‑JSON objects in metadata (e.g., `HumanMessage`) now raises “Object of type HumanMessage is not JSON serializable.” ### What I’m doing Saving a checkpoint with `PostgresSaver.put(...)` where the `metadata` includes a LangChain `HumanMessage`. ### Expected behavior - Same behavior as 2.0.21: metadata accepted (JsonPlus previously handled complex Python objects), or clear migration guidance if behavior is intentionally changed. ### Actual behavior - On 2.0.22, calling `put(...)` raises: - Exception: “Object of type HumanMessage is not JSON serializable” ### Minimal reproducible example ```python import os from langgraph.checkpoint.postgres import PostgresSaver from langgraph.checkpoint.base import empty_checkpoint from langchain_core.messages import HumanMessage PG_URI = os.getenv( "PG_URI", "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable", ) config = {"configurable": {"thread_id": "thread-mre", "checkpoint_ns": ""}} checkpoint = empty_checkpoint() metadata = { "source": "input", "step": 1, "writes": {}, "message": HumanMessage(content="hello world"), # non-JSON object } with PostgresSaver.from_conn_string(PG_URI) as saver: saver.setup() saver.put(config, checkpoint, metadata, {}) # 2.0.22 -> raises; 2.0.21 -> OK ``` ### Environment - Works: `langgraph-checkpoint-postgres==2.0.21` - Fails: `langgraph-checkpoint-postgres==2.0.22` - Python 3.10+/3.11 - psycopg 3 (binary/pool) - OS: Linux - Postgres: local instance ### Additional notes - In 2.0.21, metadata was serialized via JsonPlus (tolerated Python objects). - In 2.0.22, metadata is passed directly as JSONB (`Jsonb(get_checkpoint_metadata(...))`), which rejects non‑JSON objects. - If this change is intended, please document it and provide a migration note (e.g., require JSON-only metadata or recommend moving complex objects to channel blobs). ### System Info System Information ------------------ > OS: Linux > OS Version: #27~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 17:38:49 UTC 2 > Python Version: 3.11.12 (main, May 22 2025, 15:29:00) [GCC 13.3.0] Package Information ------------------- > langchain_core: 0.2.43 > langchain: 0.2.17 > langchain_community: 0.2.19 > langsmith: 0.1.147 > langchain_google_calendar_tools: 0.0.1 > langchain_openai: 0.1.25 > langchain_postgres: 0.0.12 > langchain_text_splitters: 0.2.4 > langchainhub: 0.1.21 > langgraph: 0.2.76 Optional packages not installed ------------------------------- > langserve Other Dependencies ------------------ > aiohttp: 3.12.14 > async-timeout: 5.0.1 > dataclasses-json: 0.6.7 > google-api-python-client>=2.104.0: Installed. No version info available. > google-auth-oauthlib>=1.1.0: Installed. No version info available. > httpx: 0.28.1 > jsonpatch: 1.33 > langchain>=0.0.335: Installed. No version info available. > langgraph-checkpoint: 2.1.1 > langgraph-sdk: 0.1.74 > langsmith-pyo3: Installed. No version info available. > numpy: 1.26.4 > openai: 1.97.1 > orjson: 3.11.0 > packaging: 24.2 > pgvector: 0.2.5 > protobuf>=4.25.0: Installed. No version info available. > psycopg: 3.2.1 > psycopg-pool: 3.2.2 > pydantic: 2.8.2 > pytz>=2023.3.post1: Installed. No version info available. > PyYAML: 6.0.2 > requests: 2.32.3 > requests-toolbelt: 1.0.0 > SQLAlchemy: 2.0.41 > sqlalchemy: 2.0.41 > tenacity: 8.5.0 > tiktoken: 0.9.0 > types-requests: 2.32.4.20250611 > typing-extensions: 4.14.1
yindo added the bugpending labels 2026-02-20 17:42:19 -05:00
yindo closed this issue 2026-02-20 17:42:19 -05:00
Author
Owner

@onestardao commented on GitHub (Aug 9, 2025):

looks like you just hit a deployment ordering failure ~ in our Problem Map that’s No.15: bootstrap-ordering.
the upgrade changed when certain type bindings are loaded, so your Namespace object is being serialized before its type handler is registered.

we solved this by enforcing a pre-deploy phase that locks type metadata before any checkpoint write happens. prevents exactly this “type not available” crash.

MIT licensed, reproducible, and it works across multi-module setups like yours.

@onestardao commented on GitHub (Aug 9, 2025): looks like you just hit a deployment ordering failure ~ in our Problem Map that’s No.15: bootstrap-ordering. the upgrade changed when certain type bindings are loaded, so your Namespace object is being serialized before its type handler is registered. we solved this by enforcing a pre-deploy phase that locks type metadata before any checkpoint write happens. prevents exactly this “type not available” crash. MIT licensed, reproducible, and it works across multi-module setups like yours.
Author
Owner

@tamaraMalysh commented on GitHub (Sep 24, 2025):

Why is that closed? I have the same issue

@tamaraMalysh commented on GitHub (Sep 24, 2025): Why is that closed? I have the same issue
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#909