{"record":{"id":"c7624d913b4db69c","repo":"nats-io/nats-server","slug":"10151","errorCode":"10151","errorMessage":"%w %s","messagePattern":"%w %s","errorType":"validation","errorClass":"ApiError (JSMirrorInvalidSubjectFilter)","httpStatus":400,"severity":"error","filePath":"server/stream.go","lineNumber":2138,"sourceCode":"\t\t\t\treturn StreamConfig{}, NewJSMirrorDurableConsumerCfgInvalidError()\n\t\t\t}\n\t\t\tif cfg.Mirror.FilterSubject != _EMPTY_ {\n\t\t\t\treturn StreamConfig{}, NewJSMirrorDurableConsumerCfgInvalidError()\n\t\t\t}\n\t\t}\n\t\tif cfg.Mirror.FilterSubject != _EMPTY_ && len(cfg.Mirror.SubjectTransforms) != 0 {\n\t\t\treturn StreamConfig{}, NewJSMirrorMultipleFiltersNotAllowedError()\n\t\t}\n\t\tif cfg.SubjectDeleteMarkerTTL > 0 {\n\t\t\t// Delete markers cannot be configured on a mirror as it would result in new\n\t\t\t// tombstones which would use up sequence numbers, diverging from the origin\n\t\t\t// stream.\n\t\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"subject delete markers forbidden on mirrors\"))\n\t\t}\n\t\t// Check subject filters overlap.\n\t\tfor outer, tr := range cfg.Mirror.SubjectTransforms {\n\t\t\tif tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {\n\t\t\t\treturn StreamConfig{}, NewJSMirrorInvalidSubjectFilterError(fmt.Errorf(\"%w %s\", ErrBadSubject, tr.Source))\n\t\t\t}\n\n\t\t\terr := ValidateMapping(tr.Source, tr.Destination)\n\t\t\tif err != nil {\n\t\t\t\treturn StreamConfig{}, NewJSMirrorInvalidTransformDestinationError(err)\n\t\t\t}\n\n\t\t\tfor inner, innertr := range cfg.Mirror.SubjectTransforms {\n\t\t\t\tif inner != outer && SubjectsCollide(tr.Source, innertr.Source) {\n\t\t\t\t\treturn StreamConfig{}, NewJSMirrorOverlappingSubjectFiltersError()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Do not perform checks if External is provided, as it could lead to\n\t\t// checking against itself (if sourced stream name is the same on different JetStream)\n\t\tif cfg.Mirror.External == nil {\n\t\t\tif !isValidAssetName(cfg.Mirror.Name) {\n\t\t\t\treturn StreamConfig{}, NewJSMirrorInvalidStreamNameError()","sourceCodeStart":2120,"sourceCodeEnd":2156,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L2120-L2156","documentation":"A mirror's SubjectTransforms entry contains an invalid source subject (or a source/destination mapping that fails ValidateMapping). The server wraps ErrBadSubject with the offending subject and returns JSMirrorInvalidSubjectFilterError (10151) via JSStreamInvalidConfigError during mirror config validation.","triggerScenarios":"AddStream/UpdateStream with Mirror.SubjectTransforms where tr.Source is non-empty and !IsValidSubject(tr.Source) — e.g. empty destination, trailing dot, invalid wildcard placement, or spaces in the subject.","commonSituations":"Typos in transform subjects like 'foo..bar' or 'foo bar'; constructing transforms programmatically with empty/invalid source strings; configs hand-edited with wildcards in illegal positions.","solutions":["Fix the SubjectTransforms source subject to a valid NATS subject (no spaces, valid tokens/wildcards)","Ensure each transform has both a valid non-empty Source and Destination","Validate subjects with server IsValidSubject semantics (tokens separated by '.', legal wildcard use) before submitting"],"exampleFix":"// before\ntf := SubjectTransformConfig{Source: \"foo..bar\", Destination: \"baz\"}\n// after\ntf := SubjectTransformConfig{Source: \"foo.bar\", Destination: \"baz\"}","handlingStrategy":"validation","validationCode":"for _, tr := range cfg.Mirror.SubjectTransforms {\n    if tr.Source != \"\" && !subjectIsValid(tr.Source) {\n        return fmt.Errorf(\"invalid mirror transform source: %q\", tr.Source)\n    }\n    if err := validateMapping(tr.Source, tr.Destination); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":"var ec *jsapi.APIError\nif errors.As(err, &ec) && ec.ErrorCode == 10151 {\n    // inspect Subjects transforms, fix invalid source, resubmit\n}","preventionTips":["Validate all transform subjects with server-equivalent rules before submit","Avoid building subject strings with raw string concatenation","Add unit tests covering transform source/destination shapes"],"tags":["jetstream","mirror","subject-transform","invalid-subject"],"backgroundTag":"invalid-subject","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}