nats-io/nats-server · error · JSStreamInvalidConfigError
stream name is required and can not contain '.', '*', '>', '
Error message
stream name is required and can not contain '.', '*', '>', '\', '/'
What it means
The stream name failed isValidAssetName: it is empty or contains the reserved characters '.', '*', '>', '\\', '/'. Stream names are used as directory names and API subjects, so wildcards and path separators are forbidden.
Source
Thrown at server/stream.go:1874
// Do not hold the jetStream lock, it will be read-locked internally.
func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account, pedantic bool) (StreamConfig, *ApiError) {
if js := s.getJetStream(); js != nil {
js.mu.RLock()
defer js.mu.RUnlock()
}
return s.checkStreamCfgLocked(config, acc, pedantic)
}
// jetStream lock (read or write) should be held, if JetStream is enabled.
func (s *Server) checkStreamCfgLocked(config *StreamConfig, acc *Account, pedantic bool) (StreamConfig, *ApiError) {
lim := &s.getOpts().JetStreamLimits
if config == nil {
return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration invalid"))
}
if !isValidAssetName(config.Name) {
return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is required and can not contain '.', '*', '>', '\\', '/'"))
}
if len(config.Name) > JSMaxNameLen {
return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is too long, maximum allowed is %d", JSMaxNameLen))
}
if len(config.Description) > JSMaxDescriptionLen {
return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream description is too long, maximum allowed is %d", JSMaxDescriptionLen))
}
var metadataLen int
for k, v := range config.Metadata {
metadataLen += len(k) + len(v)
}
if metadataLen > JSMaxMetadataLen {
return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream metadata exceeds maximum size of %d bytes", JSMaxMetadataLen))
}
cfg := *config
View on GitHub (pinned to 3a66a489d2)
Solutions
- Give the stream a non-empty name containing only letters, digits, '-', '_' (e.g. ORDERS_EU).
- Validate names with the same rules before calling AddStream.
- If you need dotted hierarchy, encode it (replace '.' with '-') or use subjects to partition instead of stream names.
- Check server version: stricter name rules were enforced in newer NATS releases.
Example fix
// before
name := "orders.eu"
cfg := jetstream.StreamConfig{Name: name}
// after
name := "orders-eu" // no '.', '*', '>', '\\', '/'
cfg := jetstream.StreamConfig{Name: name} Defensive patterns
Strategy: validation
Validate before calling
var nameBadChars = "*.>\\/"
func validStreamName(name string) error {
if name == "" { return errors.New("stream name required") }
if strings.ContainsAny(name, nameBadChars) {
return fmt.Errorf("stream name %q contains forbidden characters", name)
}
return nil
} Type guard
func isSafeStreamName(name string) bool {
return name != "" && !strings.ContainsAny(name, "*.>\\/")
} Prevention
- Validate all stream names at the config-loading boundary.
- Never reuse subject strings as stream names.
- Sanitize names derived from tenant/user input.
- Prefer [A-Za-z0-9_-] names only.
- Test stream creation with your real config files.
When it happens
Trigger: Creating a stream with name ""; names containing dots (e.g. "my.stream"), wildcards ('*','>'), slashes ('/','\\'). Also occurs when a name is derived from untrusted input or a subject string is mistakenly reused as a stream name.
Common situations: Using a subject like 'orders.eu' as the stream name; templated names from environment config with slashes; empty name when a variable fails to populate; NATS 2.10+ stricter name validation rejecting names older servers accepted.
Related errors
- stream name is too long, maximum allowed is %d
- got corrupted escaped character
- incomplete type, value pair
- DN ended with incomplete type, value pair
- errors.New(strings.Join(errs, "\n"))
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/753a058c591edaee.
Report an issue: GitHub.