nats-io/nats-server · error
unable to get subject transform for source: %v
Error message
unable to get subject transform for source: %v
What it means
While (re)building the internal source state for a stream's mirror/sources, JetStream creates a SubjectTransform for each source's Source/Destination pair via NewSubjectTransform; if construction fails, the stream update/create is aborted with this error. It indicates one of the configured source subject transforms is invalid.
Source
Thrown at server/stream.go:2799
mset.cfg.Sources = append(mset.cfg.Sources, s)
mset.cfgMu.Unlock()
var si *sourceInfo
if len(s.SubjectTransforms) == 0 {
si = &sourceInfo{name: s.Name, iname: s.iname, sf: s.FilterSubject}
} else {
si = &sourceInfo{name: s.Name, iname: s.iname}
si.trs = make([]*subjectTransform, len(s.SubjectTransforms))
si.sfs = make([]string, len(s.SubjectTransforms))
for i := range s.SubjectTransforms {
// err can be ignored as already validated in config check
si.sfs[i] = s.SubjectTransforms[i].Source
var err error
si.trs[i], err = NewSubjectTransform(s.SubjectTransforms[i].Source, s.SubjectTransforms[i].Destination)
if err != nil {
mset.mu.Unlock()
return fmt.Errorf("unable to get subject transform for source: %v", err)
}
}
}
mset.sources[s.iname] = si
if needsStartingSeqNum == nil {
needsStartingSeqNum = make(map[string]struct{})
}
needsStartingSeqNum[s.iname] = struct{}{}
} else {
// source already exists
delete(currentIName, s.iname)
}
// Remove the source if it still exists, but only if not using a pre-existing consumer.
if s.Consumer == nil {
delete(currentConsumers, getSourcingConsumerIName(s, cfg.Sources))
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Validate each Sources[i].SubjectTransform subject strings with nats.SubjectTransformPre or by testing NewSubjectTransform client-side logic (valid subject syntax).
- Fix or remove the offending Source/Destination pair in the stream config and retry UpdateStream.
- Check the wrapped error (%v) to see which transform rule was rejected.
Example fix
// before
Sources: []StreamSource{{Name: "OTHER", SubjectTransform: &SubjectTransformConfig{Source: "foo..bar"}}}
// after
Sources: []StreamSource{{Name: "OTHER", SubjectTransform: &SubjectTransformConfig{Source: "foo.*", Destination: "baz.*"}}} Defensive patterns
Strategy: validation
Validate before calling
for _, s := range cfg.Sources {
if t := s.SubjectTransform; t != nil {
if err := validTransformPair(t.Source, t.Destination); err != nil { return err }
}
} Try / catch
if err != nil && strings.HasPrefix(err.Error(), "unable to get subject transform for source") { /* fix Sources[i].SubjectTransform */ } Prevention
- Validate source transforms with a subject-syntax check before UpdateStream.
- Keep wildcard token counts equal between Source and Destination.
When it happens
Trigger: StreamConfig.Sources[i].SubjectTransform (Source/Destination) that NewSubjectTransform cannot compile, e.g. invalid wildcard or malformed subject in a source's transform, added during UpdateStream.
Common situations: Typo in transform source like 'foo.>' vs 'foo.*' misuse, empty Destination, or invalid subject characters in a mirrored-source transform.
Related errors
- subject transform from '%s' to '%s' for the source: %w
- invalid mapping destination: wildcard index out of range
- invalid mapping destination: not enough arguments passed to
- invalid mapping destination: function argument is invalid or
- invalid mapping destination: too many arguments passed to th
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/9f7b96f34e955fd9.
Report an issue: GitHub.