nats-io/nats-server · error · ApiError (JSSourceInvalidSubjectFilter)

10145

10145

Error message

%w %s

What it means

A stream source's SubjectTransforms entry has an invalid source subject or an invalid source/destination mapping. The server wraps ErrBadSubject with the offending subject (JSSourceInvalidSubjectFilterError, 10151) or fails ValidateMapping (JSSourceInvalidTransformDestinationError) during StreamSource validation.

Source

Thrown at server/stream.go:2219

	var iNames = make(map[string]struct{})
	var cNames = make(map[string]struct{})
	for _, src := range cfg.Sources {
		if src == nil || !isValidAssetName(src.Name) {
			return StreamConfig{}, NewJSSourceInvalidStreamNameError()
		}
		if _, ok := iNames[src.composeIName()]; !ok {
			iNames[src.composeIName()] = struct{}{}
		} else {
			return StreamConfig{}, NewJSSourceDuplicateDetectedError()
		}

		if src.FilterSubject != _EMPTY_ && len(src.SubjectTransforms) != 0 {
			return StreamConfig{}, NewJSSourceMultipleFiltersNotAllowedError()
		}

		for _, tr := range src.SubjectTransforms {
			if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {
				return StreamConfig{}, NewJSSourceInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source))
			}
			err := ValidateMapping(tr.Source, tr.Destination)
			if err != nil {
				return StreamConfig{}, NewJSSourceInvalidTransformDestinationError(err)
			}
		}

		// Check subject filters overlap.
		for outer, tr := range src.SubjectTransforms {
			for inner, innertr := range src.SubjectTransforms {
				if inner != outer && subjectIsSubsetMatch(tr.Source, innertr.Source) {
					return StreamConfig{}, NewJSSourceOverlappingSubjectFiltersError()
				}
			}
		}

		if c := src.Consumer; c != nil {
			if !isValidAssetName(c.Name) {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Correct the transform Source to a valid NATS subject
  2. Ensure Destination matches the source's token/wildcard structure per ValidateMapping rules
  3. Pre-validate subjects/mappings before submitting the config

Example fix

// before
tr := SubjectTransformConfig{Source: "a.>.b.>", Destination: "x"}
// after
tr := SubjectTransformConfig{Source: "a.b.c", Destination: "x.y.c"}
Defensive patterns

Strategy: validation

Validate before calling

for _, src := range cfg.Sources {
    for _, tr := range src.SubjectTransforms {
        if tr.Source != "" && !subjectIsValid(tr.Source) {
            return fmt.Errorf("invalid source transform subject: %q", tr.Source)
        }
    }
}

Try / catch

var ec *jsapi.APIError
if errors.As(err, &ec) && ec.ErrorCode == 10145 {
    // locate offending transform in cfg.Sources and fix
}

Prevention

When it happens

Trigger: AddStream/UpdateStream with Sources[].SubjectTransforms where tr.Source is non-empty and !IsValidSubject(tr.Source), or ValidateMapping(tr.Source, tr.Destination) returns an error (e.g. destination that doesn't preserve wildcard token counts).

Common situations: Typo'd subjects like 'foo..bar'; transforms mapping 3-token sources to 2-token destinations; programmatic generation of transforms with empty or malformed source strings.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/494bc1ea9d4bfa07. Report an issue: GitHub.