nats-io/nats-server · error
subject filter '%s' for the mirror %w
Error message
subject filter '%s' for the mirror %w
What it means
During stream creation/update, a mirror's FilterSubject is validated with IsValidSubject; this error wraps ErrBadSubject when the filter is non-empty and not a valid NATS subject. The stream is not created.
Source
Thrown at server/stream.go:939
jsa.mu.Unlock()
js.mu.RLock()
if isClustered {
_, reserved = js.tieredStreamAndReservationCount(a.Name, tier, cfg)
}
if err := js.checkAllLimits(&selected, tier, cfg, reserved, 0); err != nil {
js.mu.RUnlock()
return nil, err
}
js.mu.RUnlock()
jsa.mu.Lock()
}
// If mirror, check if the transforms (if any) are valid.
if cfg.Mirror != nil {
if len(cfg.Mirror.SubjectTransforms) == 0 {
if cfg.Mirror.FilterSubject != _EMPTY_ && !IsValidSubject(cfg.Mirror.FilterSubject) {
jsa.mu.Unlock()
return nil, fmt.Errorf("subject filter '%s' for the mirror %w", cfg.Mirror.FilterSubject, ErrBadSubject)
}
} else {
for _, st := range cfg.Mirror.SubjectTransforms {
if st.Source != _EMPTY_ && !IsValidSubject(st.Source) {
jsa.mu.Unlock()
return nil, fmt.Errorf("invalid subject transform source '%s' for the mirror: %w", st.Source, ErrBadSubject)
}
// check the transform, if any, is valid
if st.Destination != _EMPTY_ {
if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil {
jsa.mu.Unlock()
return nil, fmt.Errorf("subject transform from '%s' to '%s' for the mirror: %w", st.Source, st.Destination, err)
}
}
}
}
}
View on GitHub (pinned to 3a66a489d2)
Solutions
- Correct the mirror FilterSubject to a valid NATS subject (token rules, wildcards only as full tokens: *, >).
- If you want the whole mirror, remove FilterSubject (set it empty) instead of an invalid value.
- Validate with server.IsValidSubject or a subject-validation helper before calling AddStream.
Example fix
// before
Mirror: &StreamSource{Name: "ORDERS", FilterSubject: "orders..new"}
// after
Mirror: &StreamSource{Name: "ORDERS", FilterSubject: "orders.>"} Defensive patterns
Strategy: validation
Validate before calling
if cfg.Mirror != nil && cfg.Mirror.FilterSubject != "" && !nats.IsValidSubject(cfg.Mirror.FilterSubject) {
return fmt.Errorf("bad mirror filter subject: %q", cfg.Mirror.FilterSubject)
} Try / catch
cfg, err := js.AddStream(streamCfg)
if err != nil {
var apiErr *nats.APIError
if errors.As(err, &apiErr) && errors.Is(err, nats.ErrBadSubject) { /* fix subject and retry once */ }
} Prevention
- Validate all subjects with IsValidSubject before config submission.
- Avoid empty tokens and misplaced wildcards.
- Load test configs through the same validation the server applies.
When it happens
Trigger: Calling AddStream/UpdateStream with cfg.Mirror.FilterSubject containing wildcards in the wrong place, adjacent tokens (foo..bar), leading/trailing dots, spaces, or other invalid characters.
Common situations: Mirroring a subset of a remote stream and typing an invalid filter (e.g. "foo.>.*" misuse or "foo bar"), or building the filter from unvalidated user input.
Related errors
- invalid subject transform source '%s' for the mirror: %w
- subject transform from '%s' to '%s' for the mirror: %w
- subject filter '%s' for the source: %w
- got corrupted escaped character
- incomplete type, value pair
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/cfc5830b9a58ab64.
Report an issue: GitHub.