nats-io/nats-server · error · ApiError (JSStreamTransformInvalidSource)
10155
10155
Error message
%w %s
What it means
The stream's SubjectTransform.Source is not a valid NATS subject, so the transform cannot be applied. The error wraps ErrBadSubject together with the offending source string. NATS validates the transform's source strictly because republished/transformed messages depend on a well-formed subject to rewrite into the destination.
Source
Thrown at server/stream.go:2421
}
}
if len(cfg.Subjects) == 0 && len(cfg.Sources) == 0 && cfg.Mirror == nil {
return StreamConfig{}, NewJSStreamInvalidConfigError(
fmt.Errorf("stream needs at least one configured subject or be a source/mirror"))
}
// Check for MaxBytes required and it's limit
if required, limit := acc.maxBytesLimits(&cfg); required && cfg.MaxBytes <= 0 {
return StreamConfig{}, NewJSStreamMaxBytesRequiredError()
} else if limit > 0 && cfg.MaxBytes > limit {
return StreamConfig{}, NewJSStreamMaxStreamBytesExceededError()
}
// Check the subject transform if any
if cfg.SubjectTransform != nil {
if cfg.SubjectTransform.Source != _EMPTY_ && !IsValidSubject(cfg.SubjectTransform.Source) {
return StreamConfig{}, NewJSStreamTransformInvalidSourceError(fmt.Errorf("%w %s", ErrBadSubject, cfg.SubjectTransform.Source))
}
err := ValidateMapping(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
if err != nil {
return StreamConfig{}, NewJSStreamTransformInvalidDestinationError(err)
}
}
// If we have a republish directive check if we can create a transform here.
if cfg.RePublish != nil {
// Check to make sure source is a valid subset of the subjects we have.
// Also make sure it does not form a cycle.
// Empty same as all.
if cfg.RePublish.Source == _EMPTY_ {
if pedantic {
return StreamConfig{}, NewJSPedanticError(fmt.Errorf("republish source can not be empty"))
}
cfg.RePublish.Source = fwcsView on GitHub (pinned to 3a66a489d2)
Solutions
- Fix cfg.SubjectTransform.Source to a valid NATS subject (letters, digits, '_' '-' '/', '*' per token, '>' only as last token).
- Validate the string with nats.IsValidSubject (or server.IsValidSubject) before submitting the config.
- Trim whitespace or resolve unsubstituted template variables before calling AddStream.
Example fix
// before
js.AddStream(&nats.StreamConfig{Name: "s", Subjects: []string{"events.>"}, SubjectTransform: &nats.SubjectTransform{Source: "events .>"}})
// after
js.AddStream(&nats.StreamConfig{Name: "s", Subjects: []string{"events.>"}, SubjectTransform: &nats.SubjectTransform{Source: "events.>", Destination: "archive.events.>"}}) Defensive patterns
Strategy: validation
Validate before calling
func validTransformSource(t *nats.SubjectTransform) error {
if t == nil { return nil }
if t.Source == "" { return nil }
if !isValidSubject(t.Source) {
return fmt.Errorf("transform source %q is not a valid subject", t.Source)
}
return nil
} Type guard
func hasValidTransformSource(t *nats.SubjectTransform) bool {
return t == nil || t.Source == "" || isValidSubject(t.Source)
} Try / catch
var jsErr *nats.JSApiError
if _, err := js.AddStream(cfg); err != nil {
if errors.As(err, &jsErr) && errors.Is(err, nats.ErrBadSubject) || strings.Contains(err.Error(), "bad subject") {
log.Printf("fix SubjectTransform.Source: %v", err)
}
} Prevention
- Validate user-supplied transform subjects with the library's subject validator before submit
- Trim and resolve template variables in config pipelines
- Test transform configs against a local nats-server in CI
When it happens
Trigger: StreamConfig.Add/Update with cfg.SubjectTransform = &nats.SubjectTransform{Source: "not a subject"} — strings with spaces, empty source, or illegal wildcard placement (e.g. 'foo.**' or a token like 'foo.>'). Check runs whenever SubjectTransform != nil and Source is non-empty.
Common situations: User-supplied transform configuration interpolated into StreamConfig without validation; template variables not substituted (e.g. Source: "{{subject}}"); trailing whitespace or typos in config files.
Related errors
- stream republish transform from '%s' to '%s': %w
- 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 subject transform from '%s' to '%s': %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1d90949ae20c8f6d.
Report an issue: GitHub.