netbirdio/netbird · error
parse log level: %w
Error message
parse log level: %w
What it means
Returned by embed.New when Options.LogLevel is non-empty and logrus.ParseLevel rejects it. Valid levels are panic, fatal, error, warn, warning, info, debug and trace (case-insensitive). The embedded client reuses the process-global logrus logger, so the level must be a valid logrus level string.
Source
Thrown at client/embed/embed.go:168
func New(opts Options) (*Client, error) {
if err := opts.validateCredentials(); err != nil {
return nil, err
}
if opts.MTU != nil {
if err := iface.ValidateMTU(*opts.MTU); err != nil {
return nil, fmt.Errorf("invalid MTU: %w", err)
}
}
if opts.LogOutput != nil {
logrus.SetOutput(opts.LogOutput)
}
if opts.LogLevel != "" {
level, err := logrus.ParseLevel(opts.LogLevel)
if err != nil {
return nil, fmt.Errorf("parse log level: %w", err)
}
logrus.SetLevel(level)
}
if !opts.NoUserspace {
if err := os.Setenv(netstack.EnvUseNetstackMode, "true"); err != nil {
return nil, fmt.Errorf("setenv: %w", err)
}
if err := os.Setenv(netstack.EnvSkipProxy, "true"); err != nil {
return nil, fmt.Errorf("setenv: %w", err)
}
}
if opts.StatePath != "" {
// TODO: Disable state if path not provided
if err := os.Setenv("NB_DNS_STATE_FILE", opts.StatePath); err != nil {
return nil, fmt.Errorf("setenv: %w", err)
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Use one of: panic, fatal, error, warn, warning, info, debug, trace.
- Validate with logrus.ParseLevel before calling embed.New when the string comes from user input or config files.
- Leave LogLevel empty to keep the default (info).
Example fix
// before
client, err := embed.New(embed.Options{LogLevel: cfg.LogLevel})
// after
if _, perr := logrus.ParseLevel(cfg.LogLevel); cfg.LogLevel != "" && perr != nil {
return fmt.Errorf("bad log level %q: %w", cfg.LogLevel, perr)
}
client, err := embed.New(embed.Options{LogLevel: cfg.LogLevel}) Defensive patterns
Strategy: validation
Validate before calling
import "github.com/sirupsen/logrus"
if opts.LogLevel != "" {
if _, err := logrus.ParseLevel(opts.LogLevel); err != nil {
return fmt.Errorf("invalid log level %q: %w", opts.LogLevel, err)
}
} Prevention
- Define an allowlist of level constants in your own config schema instead of free-form strings.
- Validate config at load time, not at embed.New time.
When it happens
Trigger: Calling embed.New with LogLevel set to values like "verbose", "err", "WARN " (trailing space), "INFO" works but "informational", or an empty-ish string like " ".
Common situations: Passing a level name from a different logging library (zap: "dpanic"; slog: "WARN" is fine but slog numeric levels are not); reading the level from an env var that is unset-but-not-empty; typo or case mistakes are tolerated but any unknown word fails.
Related errors
- invalid MTU: %w
- invalid dns labels: %w
- unknown log level: %s. Available levels are: panic, fatal, e
- failed initializing log %v
- create config: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/bf09d46168e11ecb.
Report an issue: GitHub.