The SQLite and Postgres stores save a namespace as its labels joined
with `.`, so a label containing `.` could resolve to a different
namespace: `("foo.bar",)` and `("foo", "bar")` share the same row. This
rejects those labels at every entry point.
- `BaseStore` and `AsyncBatchedBaseStore`: `get`, `search`, `delete`,
and `list_namespaces` (sync and async) reject labels that are empty, not
strings, or contain `.`. The check runs before an op is queued, so one
caller's bad label can't fail other callers' concurrent requests.
- New `langgraph.store.base.validate_op_namespace(op)` applies the same
label checks to a single op. `SqliteStore`/`AsyncSqliteStore` and
`PostgresStore`/`AsyncPostgresStore` call it from `_group_ops` before
any SQL runs, which covers direct `batch`/`abatch` calls. Other stores
that serialize namespaces as delimited text can call it too.
- Unchanged: hierarchical prefix search, empty-prefix `search(())`, `*`
wildcards in `list_namespaces`, and the existing `put` rules.
## Release note
`get`, `search`, `delete`, and `list_namespaces` now raise
`InvalidNamespaceError` for labels that are empty, not strings, or
contain `.`, where they previously returned `None` or `[]` (or, on the
SQLite and Postgres stores, matched a different namespace). `put`
already rejected these labels, so nothing written through `put` becomes
unreachable.
## Release order
Release `langgraph-checkpoint` first. `langgraph-checkpoint-sqlite` and
`langgraph-checkpoint-postgres` import `validate_op_namespace`, so they
need the `langgraph-checkpoint` release that ships it. `main` already
has `libs/checkpoint` at 4.3.0 and requires
`langgraph-checkpoint>=4.3.0` in both stores (from #8544), so this must
merge before 4.3.0 is released; if 4.3.0 ships first, bump to the next
version and raise both requirements to it. That also guarantees the
pre-queue checks are installed: with an older `langgraph-checkpoint`, an
invalid op would fail inside the shared `abatch` and reject the calls
batched with it.
---------
Co-authored-by: Baihao Wang <byhow@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
TypedDict values don't structurally satisfy dict[str, Any] since dict
implies full mutability. Mapping[str, Any] accepts both plain dicts and
TypedDicts while still requiring string keys, matching what put()
actually needs from callers.
Fixes#8616
Verified by running lint/type/test locally across checkpoint,
checkpoint-sqlite, checkpoint-postgres, prebuilt, sdk-py, and a scoped
langgraph subset.
LinkedIn: https://linkedin.com/in/lisandro-navarra
---------
Co-authored-by: Mason Daugherty <github@mdrxy.com>
## Summary
- replace Python lint type-checking from mypy to ty across LangGraph
packages
- remove mypy config/cache wiring and mypy-only references
- regenerate uv locks with ty 0.0.43
## Verification
- git diff --check
- make lint_package && make lint_tests in libs/langgraph
- make lint_package && make lint_tests in libs/checkpoint
- make lint_package && make lint_tests in libs/checkpoint-sqlite
- make lint_package && make lint_tests in libs/checkpoint-postgres
- make lint_package && make lint_tests in libs/prebuilt
- make lint_package && make lint_tests in libs/cli
- make lint in libs/sdk-py
- make lint in libs/checkpoint-conformance
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: open-swe[bot] <215916821+open-swe[bot]@users.noreply.github.com>
### Description
`test_embed_with_path` was failing on x86_64 architecture due to numeric
precision differences. `pytest.approx` was already used later on in this
test for float comparison, so this PR just updates a missed assertion.
Fixes https://github.com/langchain-ai/langgraph/issues/5845
### Description
* Set `ensure_ascii=False` for all `json.dumps` calls in
`get_text_at_path`. Preserves non-ASCII text instead of embedding
`\uXXXX` escapes.
**Before**
```python
store.put(("user_123", "memories"), "1", {"text": "这是中文"})
# embeds {"text": "\\u8fd9\\u662f\\u4e2d\\u6587"}
```
**After**
```python
store.put(("user_123", "memories"), "1", {"text": "这是中文"})
# embeds {"text": "这是中文"}
```
### Tests & Docs
* Add unit test `test_non_ascii` that writes three records (Chinese,
Japanese, Korean) to an `InMemoryStore`, searches with the same strings,
and asserts the correct top hit with a score >= 0.15 for each.
### Issue
Fixes#5946
This commit fixes#5503
Gist of it is:
- `asyncio.exception.InvalidStateError` were being raised when the
future was cancelled
- this exception bubbled up and killed the background task
- `AsyncBatchedBaseStore` stopped doing queries because the background
task wasn't running anymore
This commit adds some "if future is not done" checks to guard against
this.
* Migrate to `uv`
* Format `pyproject.toml` files properly
* Remove upper bounds on dependencies, and bounds on dev dependencies
(we should be using latest)
* Move to hatch for packaing
In the future we should:
* Set up dependabot / automate lockfile updates and tests
* Add tests for min compatible versions (I'll do this right after merge)
* Use dynamic versioning
* Bump `pydantic` to v2.11.4 in the lockfile, we have some tests failing
- This should only be used in very specific circunstances, sqlite or
postgres adapters much more appropriate in most circunstances
---------
Co-authored-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>