langchain-ai / langchain-ai/langgraph
numpy scalars (np.float64, np.int64, np.bool_) fail to serialize in JsonPlusSerializer
- Dominant language
- Python
- Stars
- 41.8k
- Forks
- 7.1k
- Avg merge
- 23h 7m
- Merged PRs (30d)
- 30
Description
### Checked other resources
- [X] This is a bug, not a usage question.
- [X] I added a clear and descriptive title that summarizes this issue.
- [X] I used the GitHub search to find a similar question and didn't find it.
- [X] I am sure that this is a bug in LangGraph rather than my code.
- [X] The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).
- [X] This is not related to the langchain-community package.
- [X] I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.
### Related Issues / PRs
- #8689 concerns `datetime64`/`timedelta64` **arrays** failing the `memoryview()` fast path. That is a different branch of the same `_msgpack_default` numpy handling; this report is about numpy **scalars**, which have no branch at all.
### Reproduction Steps / Example Code (Python)
```python
import numpy as np
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
s = JsonPlusSerializer()
arr = np.array([1.0, 2.0])
print(s.loads_typed(s.dumps_typed(arr))) # array([1., 2.]) -- fine
print(s.loads_typed(s.dumps_typed(arr[0]))) # TypeError
```
Every numpy scalar type fails the same way:
```python
for value in (arr[0], arr.mean(), np.float64(1.5), np.int64(7),
np.bool_(True), np.float32(1.5)):
try:
s.loads_typed(s.dumps_typed(value))
print("ok ", type(value).__name__)
except TypeError as e:
print("FAIL", type(value).__name__, "->", e)
```
```
FAIL float64 -> Type is not msgpack serializable: numpy.float64
FAIL float64 -> Type is not msgpack serializable: numpy.float64
FAIL float64 -> Type is not msgpack serializable: numpy.float64
FAIL int64 -> Type is not msgpack serializable: numpy.int64
FAIL bool -> Type is not msgpack serializable: numpy.bool
FAIL float32 -> Type is not msgpack serializable: numpy.float32
```
Note the asymmetry: `np.array(1.5)` (a 0-d array) round-trips fine, but `np.float64(1.5)` — which is what indexing or reducing that same array returns — does not.
### Error Message and Stack Trace (if applicable)
```
TypeError: Type is not msgpack serializable: numpy.float64
```
Reached through `JsonPlusSerializer.dumps_typed` -> `_msgpack_enc` -> `ormsgpack.packb(default=_msgpack_default)`.
### Description
`JsonPlusSerializer._msgpack_default` has a branch for `numpy.ndarray` (encoded as `EXT_NUMPY_ARRAY`, `libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py:515`), but no branch for `numpy.generic` — the base class of every numpy scalar. Scalars therefore fall through to the final `raise TypeError`.
This matters because numpy scalars are what ordinary numpy/pandas code actually produces. `arr[0]`, `arr.mean()`, `df["col"].iloc[0]`, `df["col"].sum()` and most aggregations all return `np.float64`/`np.int64`, not a Python `float`/`int`. Any node that computes a number with pandas or numpy and writes it into graph state will hit this the moment a real checkpointer serializes the state.
It is easy to miss in testing: `MemorySaver`/`InMemorySaver` never serializes, so graph tests pass and the failure only appears against `PostgresSaver`/`SqliteSaver`. In our case a live run died with `TypeError: Type is not msgpack serializable: numpy.float64` while every graph test was green.
The values are also trivially representable — `np.float64` is a `float` subclass and `np.int64` an integer — so the current behaviour is a gap rather than a fundamental limitation. A `np_mod.generic` branch alongside the existing `ndarray` one would cover all scalar dtypes.
I have a fix and regression tests ready locally, covering `float64`/`float32`/`int64`/`bool_` plus the `datetime64`/`timedelta64` scalar dtypes, and preserving dtype through the round-trip rather than silently downcasting to Python builtins. Happy to open a PR — per `require-issue-link`, could a maintainer assign this to me first?
### System Info
```
langgraph 1.2.10
langgraph-checkpoint 4.1.1
numpy 2.4.3
ormsgpack 1.12.2
Python 3.13.3
Platform macOS-26.6.2-arm64
```
Also reproduced against `main` at f09cfe8.
Contributor guide
Research direction
Start in libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py around line 515, reading JsonPlusSerializer._msgpack_default and its existing numpy.ndarray handling. Run the provided scalar reproduction first, then inspect the serializer's round-trip tests if present. Done means numpy numeric, boolean, datetime64, and timedelta64 scalars serialize and deserialize without the current TypeError while preserving dtype.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 73/100