{"record":{"id":"96121302fd5785d9","repo":"nats-io/nats-server","slug":"invalid-subject-transform-source-s-for-the-mirr","errorCode":null,"errorMessage":"invalid subject transform source '%s' for the mirror: %w","messagePattern":"invalid subject transform source '(.+?)' for the mirror: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream.go","lineNumber":945,"sourceCode":"\t\t\tjs.mu.RUnlock()\n\t\t\treturn nil, err\n\t\t}\n\t\tjs.mu.RUnlock()\n\t\tjsa.mu.Lock()\n\t}\n\n\t// If mirror, check if the transforms (if any) are valid.\n\tif cfg.Mirror != nil {\n\t\tif len(cfg.Mirror.SubjectTransforms) == 0 {\n\t\t\tif cfg.Mirror.FilterSubject != _EMPTY_ && !IsValidSubject(cfg.Mirror.FilterSubject) {\n\t\t\t\tjsa.mu.Unlock()\n\t\t\t\treturn nil, fmt.Errorf(\"subject filter '%s' for the mirror %w\", cfg.Mirror.FilterSubject, ErrBadSubject)\n\t\t\t}\n\t\t} else {\n\t\t\tfor _, st := range cfg.Mirror.SubjectTransforms {\n\t\t\t\tif st.Source != _EMPTY_ && !IsValidSubject(st.Source) {\n\t\t\t\t\tjsa.mu.Unlock()\n\t\t\t\t\treturn nil, fmt.Errorf(\"invalid subject transform source '%s' for the mirror: %w\", st.Source, ErrBadSubject)\n\t\t\t\t}\n\t\t\t\t// check the transform, if any, is valid\n\t\t\t\tif st.Destination != _EMPTY_ {\n\t\t\t\t\tif _, err = NewSubjectTransform(st.Source, st.Destination); err != nil {\n\t\t\t\t\t\tjsa.mu.Unlock()\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"subject transform from '%s' to '%s' for the mirror: %w\", st.Source, st.Destination, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Setup our internal indexed names here for sources and check if the transforms (if any) are valid.\n\tfor _, ssi := range cfg.Sources {\n\t\tif len(ssi.SubjectTransforms) == 0 {\n\t\t\t// check the filter, if any, is valid\n\t\t\tif ssi.FilterSubject != _EMPTY_ && !IsValidSubject(ssi.FilterSubject) {\n\t\t\t\tjsa.mu.Unlock()","sourceCodeStart":927,"sourceCodeEnd":963,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L927-L963","documentation":"Stream-creation validation (checkStreamCfgLocked path for mirrors): a Mirror.SubjectTransforms entry has a non-empty Source that failed IsValidSubject — the source subject contains invalid characters or wildcards ('>', '*', '.') used illegally for a mirror transform source. Wrapped with ErrBadSubject semantics.","triggerScenarios":"AddStream/UpdateStream with cfg.Mirror.SubjectTransforms containing an entry whose Source is malformed (empty tokens, bad wildcard placement, illegal characters).","commonSituations":"Typos in transform source subjects, generating transforms programmatically from invalid input, or copying filter-style wildcards that are illegal as transform sources.","solutions":["Fix st.Source to a valid NATS subject.","Remove the invalid transform entry if the source is not needed.","Validate each transform source before constructing the config."],"exampleFix":"// before\nSubjectTransforms: []SubjectTransformConfig{{Source: \"orders..in\"}}\n// after\nSubjectTransforms: []SubjectTransformConfig{{Source: \"orders.in\"}}","handlingStrategy":"validation","validationCode":"for _, st := range cfg.Mirror.SubjectTransforms {\n  if st.Source != \"\" && !nats.IsValidSubject(st.Source) { return fmt.Errorf(\"bad transform source %q\", st.Source) }\n}","typeGuard":null,"tryCatchPattern":"_, err := js.AddStream(cfg)\nif err != nil && strings.Contains(err.Error(), \"invalid subject transform source\") { /* correct st.Source and resubmit */ }","preventionTips":["Validate every transform Source at config-build time.","Generate transforms from validated inputs only."],"tags":["jetstream","mirror","subject-transform","validation"],"backgroundTag":"invalid-nats-subject","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}