Skip to content

fix(kv): publish KV mutations through the JetStream API prefix for domain contexts - #1011

Open
thejoeejoee wants to merge 2 commits into
nats-io:mainfrom
thejoeejoee:fix/kv-domain-prefix
Open

fix(kv): publish KV mutations through the JetStream API prefix for domain contexts#1011
thejoeejoee wants to merge 2 commits into
nats-io:mainfrom
thejoeejoee:fix/kv-domain-prefix

Conversation

@thejoeejoee

Copy link
Copy Markdown

Fixes #1010.

Problem

When a JetStreamContext targets a JetStream domain (nc.jetstream(domain="leaf")), the API prefix becomes $JS.<domain>.API, but KeyValue mutations (put, create, update, delete, purge) still published to the unqualified local $KV.<bucket>.<key> subject. Over a leafnode this fails with NoStreamResponseError, while reads (bucket lookup, get, watch) already worked through the domain-scoped API.

Fix

Match the Go client behavior (nats.go useJSPfx): when the context's API prefix is not the default $JS.API, prepend it to the KV data subject for mutations, yielding $JS.<domain>.API.$KV.<bucket>.<key>.

Reads (get, history, keys, watch, purge_deletes) intentionally keep the local $KV. prefix: stream subjects are not prefixed, and watchers filter on the stream's subjects. This mirrors the Go split between pre (read) and the JS-prefixed mutation subject.

Tests

  • New SingleJetStreamServerDomainTestCase (nats/tests/utils.py) starting a server with jetstream { domain: "test-domain" } (nats/tests/conf/js-domain.conf).
  • New KVDomainTest (nats/tests/test_js.py):
    • test_kv_mutations_use_domain_qualified_subject — spies on the connection and asserts every mutation request goes to $JS.test-domain.API.$KV.TEST_DOMAIN.<key> (regression test for the reported bug).
    • test_kv_mutations_work_over_domain — full put/get/create/update/CAS/delete/purge round-trip through a domain-scoped context.
    • test_kv_binding_via_key_value_uses_domain — covers the key_value() binding path from the issue.

All nats/tests pass locally (237 passed, 21 skipped).

Out of scope

ObjectStore mutations have the same unqualified-subject issue ($O.<bucket>.C/M.). Left for a follow-up to keep this change minimal.

@thejoeejoee
thejoeejoee marked this pull request as ready for review August 26, 2026 12:32
@caspervonb caspervonb added the nats-legacy Legacy asyncio NATS client label Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

nats-legacy Legacy asyncio NATS client

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KV mutations ignore JetStream domain and publish to the local $KV subject

2 participants