nats-io/nats-server · error
stream subject transform from '%s' to '%s': %w
Error message
stream subject transform from '%s' to '%s': %w
What it means
Stream-creation validation: the stream-level cfg.SubjectTransform could not be constructed via NewSubjectTransform(source, destination); the input transform on the stream config is invalid (bad subject syntax, illegal wildcards in source/destination mapping). The offending pair and the transform error are wrapped in the message.
Source
Thrown at server/stream.go:1053
// protection: sa.Created is immutable.
mset.created = sa.Created
}
// Start our signaling routine to process consumers.
mset.sigq = newIPQueue[*cMsg](s, qpfx+"obs") // of *cMsg
go mset.signalConsumersLoop()
// For no-ack consumers when we are interest retention.
if cfg.Retention != LimitsPolicy {
mset.ackq = newIPQueue[uint64](s, qpfx+"acks")
}
// Check for input subject transform
if cfg.SubjectTransform != nil {
tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
if err != nil {
jsa.mu.Unlock()
return nil, fmt.Errorf("stream subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)
}
mset.itr = tr
}
// Check for RePublish.
if cfg.RePublish != nil {
tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination)
if err != nil {
jsa.mu.Unlock()
return nil, fmt.Errorf("stream republish transform from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err)
}
// Assign our transform for republishing.
mset.tr = tr
}
storeDir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name)
jsa.mu.Unlock()
// Bind to the user account.View on GitHub (pinned to 3a66a489d2)
Solutions
- Align the destination's token structure with the source (each wildcard maps one token).
- Check both subjects with IsValidSubject and test with NewSubjectTransform before calling AddStream.
- Remove cfg.SubjectTransform if no stream-wide remap is intended.
Example fix
// before
SubjectTransform: &SubjectTransformConfig{Source: "events.*", Destination: "archive.events.*.v2"}
// after
SubjectTransform: &SubjectTransformConfig{Source: "events.*", Destination: "archive.events.*"} Defensive patterns
Strategy: validation
Validate before calling
if cfg.SubjectTransform != nil {
if _, err := server.NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination); err != nil { return err }
} Try / catch
_, err := js.AddStream(cfg)
if err != nil && strings.Contains(err.Error(), "stream subject transform") { /* fix transform, resubmit */ } Prevention
- Keep the stream-wide transform structurally simple (same token count, 1:1 wildcard mapping).
- Test with NewSubjectTransform locally before creating the stream.
When it happens
Trigger: AddStream with cfg.SubjectTransform whose Source/Destination pair is invalid: token-count mismatch, illegal wildcard usage, or invalid characters in either subject.
Common situations: Remapping all messages published to a stream into a different subject space; typical mistake is destination with more tokens than source or wildcards in the wrong token position.
Related errors
- invalid subject transform source '%s' for the mirror: %w
- subject transform from '%s' to '%s' for the mirror: %w
- subject transform from '%s' to '%s' for the source: %w
- stream republish transform from '%s' to '%s': %w
- 10155
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/d27dcef823bd92e8.
Report an issue: GitHub.