Skip to content

Fix NATS JetStream native scheduled send (err 10190) and add configurable schedule-subject suffix.#3017

Merged
jeremydmiller merged 4 commits into
JasperFx:mainfrom
midub:nats-scheduled-delivery
Jun 3, 2026
Merged

Fix NATS JetStream native scheduled send (err 10190) and add configurable schedule-subject suffix.#3017
jeremydmiller merged 4 commits into
JasperFx:mainfrom
midub:nats-scheduled-delivery

Conversation

@midub

@midub midub commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Problem

Wolverine.Nats fails to send any scheduled message over NATS JetStream native scheduling (NATS Server 2.12+). The transport publishes the scheduling control message to the same subject it sets as the Nats-Schedule-Target header, but NATS requires the control message to be published to a subject different from the target. The server rejects the publish:

{"error":{"code":400,"err_code":10190,"description":"message schedules target is invalid"}}

The send throws, nothing is materialized, and the consumer never receives the message.

Fix

JetStreamPublisher now keeps Nats-Schedule-Target = the real destination subject (where the listener's exact-FilterSubject consumer reads and the server materializes the message at fire time) and publishes the control message to a derived subject:

  • Derived subject defaults to <subject>.scheduled.
  • Configurable per endpoint via UseScheduleSubjectSuffix(...).
  • Both the target and the schedule subject must be covered by the same stream → use a prefix.> filter (a single-token * / exact-subject filter will not cover the derived subject).
  • An empty/whitespace suffix falls back to .scheduled, so the control subject can never collapse onto the target again.

Tests

  • schedule_send_over_native_jetstream_scheduling — drives the native path by putting .UseJetStream(stream) on the publishing endpoint. Times out before the fix, passes after. Asserts the native path is engaged (not the durable fallback). Skips on NATS < 2.12.
  • overridden_suffix_is_used_for_native_scheduling — provisions the stream with explicit subjects covering only the target and the .override-scheduled subject (default .scheduled deliberately not covered), so delivery only succeeds if the configured suffix is actually applied.

@midub midub requested review from Copilot June 3, 2026 14:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes NATS JetStream native scheduled-send failures (err 10190) by publishing the scheduling “control” message to a derived subject (target + suffix) while keeping Nats-Schedule-Target as the true destination.

Changes:

  • Add configurable schedule-subject suffix on NatsEndpoint and plumb it into JetStreamPublisher
  • Adjust JetStream scheduled publish logic to use a derived schedule subject
  • Add tests and documentation describing the err 10190 behavior and the stream subject coverage requirements

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Transports/NATS/Wolverine.Nats/Internal/NatsSender.cs Pass per-endpoint schedule suffix into JetStreamPublisher
src/Transports/NATS/Wolverine.Nats/Internal/NatsEndpoint.cs Introduce ScheduleSubjectSuffix setting with docs
src/Transports/NATS/Wolverine.Nats/Internal/JetStreamPublisher.cs Publish scheduled control messages to subject + suffix to avoid err 10190
src/Transports/NATS/Wolverine.Nats/Configuration/NatsSubscriberConfiguration.cs Add fluent configuration for schedule suffix
src/Transports/NATS/Wolverine.Nats.Tests/ScheduledMessageDeliveryTests.cs Integration test reproducing/guarding against err 10190
src/Transports/NATS/Wolverine.Nats.Tests/NatsScheduleSubjectSuffixTests.cs Unit tests for default + configuration round-trip
docs/guide/messaging/transports/nats.md Document scheduling subject derivation and stream wildcard requirements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Transports/NATS/Wolverine.Nats.Tests/ScheduledMessageDeliveryTests.cs Outdated
Comment thread docs/guide/messaging/transports/nats.md Outdated
@jeremydmiller

Copy link
Copy Markdown
Member

@midub I'll try to get this reviewed and in today

@jeremydmiller

Copy link
Copy Markdown
Member

@midub Looks good to me, I'll be getting this in today. I think that will be 6.4.2, but might be 6.5. Depends on what else comes in in the meantime.

@jeremydmiller jeremydmiller merged commit 35279da into JasperFx:main Jun 3, 2026
23 checks passed
This was referenced Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants