nats-io/nats-server · error
subject transform from '%s' to '%s' for the source: %w
Error message
subject transform from '%s' to '%s' for the source: %w
What it means
Stream-creation validation for Sources: a Source.SubjectTransforms entry could not be constructed via NewSubjectTransform(source, destination) — the source/destination pair is not a valid subject transform (bad subject syntax or invalid wildcard usage in the mapping). The failing pair and underlying transform error are echoed.
Source
Thrown at server/stream.go:976
// Setup our internal indexed names here for sources and check if the transforms (if any) are valid.
for _, ssi := range cfg.Sources {
if len(ssi.SubjectTransforms) == 0 {
// check the filter, if any, is valid
if ssi.FilterSubject != _EMPTY_ && !IsValidSubject(ssi.FilterSubject) {
jsa.mu.Unlock()
return nil, fmt.Errorf("subject filter '%s' for the source: %w", ssi.FilterSubject, ErrBadSubject)
}
} else {
for _, st := range ssi.SubjectTransforms {
if st.Source != _EMPTY_ && !IsValidSubject(st.Source) {
jsa.mu.Unlock()
return nil, fmt.Errorf("subject filter '%s' for the source: %w", st.Source, ErrBadSubject)
}
// check the transform, if any, is valid
if st.Destination != _EMPTY_ {
if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil {
jsa.mu.Unlock()
return nil, fmt.Errorf("subject transform from '%s' to '%s' for the source: %w", st.Source, st.Destination, err)
}
}
}
}
}
// Check for overlapping subjects with other streams.
// These are not allowed for now.
if jsa.subjectsOverlap(cfg.Subjects, nil) {
jsa.mu.Unlock()
return nil, NewJSStreamSubjectOverlapError()
}
// Setup the internal clients.
c := s.createInternalJetStreamClient()
ic := s.createInternalJetStreamClient()
// Work out the stream ingest limits.View on GitHub (pinned to 3a66a489d2)
Solutions
- Make source and destination token structures compatible (wildcards map 1:1).
- Run NewSubjectTransform locally to reproduce the exact reason.
- Empty the destination if no transform is needed for that source.
Example fix
// before
{Source: "a.*", Destination: "b.*.c"}
// after
{Source: "a.*", Destination: "b.*"} Defensive patterns
Strategy: validation
Validate before calling
for _, s := range cfg.Sources {
for _, st := range s.SubjectTransforms {
if st.Destination != "" {
if _, err := server.NewSubjectTransform(st.Source, st.Destination); err != nil { return err }
}
}
} Try / catch
_, err := js.AddStream(cfg)
if err != nil && strings.Contains(err.Error(), "subject transform from") { /* fix token mapping, resubmit */ } Prevention
- Match source/destination token counts and wildcard positions.
- Validate transform pairs with NewSubjectTransform before deploy.
When it happens
Trigger: AddStream/UpdateStream where cfg.Sources[i].SubjectTransforms has a Destination that does not map from its Source (token-count or wildcard mismatch).
Common situations: Rewriting subjects across sourced streams with mismatched patterns, e.g. source "a.*" mapped to a three-token destination.
Related errors
- invalid subject transform source '%s' for the mirror: %w
- subject transform from '%s' to '%s' for the mirror: %w
- subject filter '%s' for the source: %w
- stream subject transform from '%s' to '%s': %w
- stream republish transform from '%s' to '%s': %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/a0c081b620a8d5b9.
Report an issue: GitHub.