nats-io/nats-server · error
encountered panic without a token %v
Error message
encountered panic without a token %v
What it means
This error is produced by a deferred panic-recovery helper in server/opts.go when a panic occurs during configuration processing but no configuration token was recorded to attach the panic to. Because the library cannot attribute the panic to a specific config option, it emits this generic error into the collected errors list. It exists so config parsing panics become normal errors instead of crashing the server.
Source
Thrown at server/opts.go:1009
*lastToken = tk
}
return tk, tk.Value()
default:
return nil, v
}
}
// use in defer to recover from panic and turn it into an error associated with last token
func convertPanicToErrorList(lastToken *token, errors *[]error) {
// only recover if an error can be stored
if errors == nil {
return
} else if err := recover(); err == nil {
return
} else if lastToken != nil && *lastToken != nil {
*errors = append(*errors, &configErr{*lastToken, fmt.Sprint(err)})
} else {
*errors = append(*errors, fmt.Errorf("encountered panic without a token %v", err))
}
}
// use in defer to recover from panic and turn it into an error associated with last token
func convertPanicToError(lastToken *token, e *error) {
// only recover if an error can be stored
if e == nil || *e != nil {
return
} else if err := recover(); err == nil {
return
} else if lastToken != nil && *lastToken != nil {
*e = &configErr{*lastToken, fmt.Sprint(err)}
} else {
*e = fmt.Errorf("%v", err)
}
}
// configureSystemAccount configures a system accountView on GitHub (pinned to 3a66a489d2)
Solutions
- Inspect the panic value %v in the message to find which parse path panicked.
- Validate your config file values (correct types for ports, URLs, arrays) before starting the server.
- Binary-search the config file by removing sections until the panic disappears, then fix that section.
- If caused by a library bug on a valid config, report it with the redacted config.
Example fix
// before (config triggering a pre-token panic)
cluster: 12345
// after
cluster {
port: 12345
} Defensive patterns
Strategy: validation
Validate before calling
// sanity-check config values' types before starting the server
for key, val := range cfg {
switch val.(type) {
case map[string]any, []any, string, int64, bool, nil:
default:
fmt.Printf("unexpected type %T for key %s\n", val, key)
}
} Type guard
func isScalarOrBlock(v any) bool {
switch v.(type) {
case map[string]any, []any, string, int64, float64, bool, nil:
return true
}
return false
} Prevention
- Validate the config file structure before deployment.
- Keep option blocks in documented map/list shapes.
- Test config changes in a staging server first.
When it happens
Trigger: Any panic raised inside a parse* function (parseCluster, parseGateway, etc.) invoked through the recover helper whose lastToken is nil — i.e., the panic fired before a config block token was set.
Common situations: Malformed or unexpected config value types causing type-assertion panics very early in option parsing; a parser bug triggered before token assignment.
Related errors
- %v
- mqtt authentication token not compatible with presence of us
- ack wait must be a positive value
- JS API timeout must be a positive value
- mqtt requires JetStream to be enabled if running in standalo
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/7ad42862dcbb1dd3.
Report an issue: GitHub.