jaegertracing/jaeger · error

invalid configuration: %w

Error message

invalid configuration: %w

What it means

After a successful Viper unmarshal, LoadConfigFromViper calls Config.Validate() and wraps any validation failure as `invalid configuration: %w`. This means the config parsed but is semantically rejected — either by storageconfig.Config.Validate() (backend-specific constraints) or because more than one trace backend was configured for the remote-storage service.

Source

Thrown at cmd/remote-storage/app/config.go:38

	GRPC    configgrpc.ServerConfig `mapstructure:"grpc"`
	Tenancy tenancy.Options         `mapstructure:"multi_tenancy"`
	// This configuration is the same as of the main `jaeger` binary,
	// but only one backend should be defined.
	Storage storageconfig.Config `mapstructure:"storage"`
}

// LoadConfigFromViper loads the configuration from Viper.
func LoadConfigFromViper(v *viper.Viper) (*Config, error) {
	cfg := &Config{}

	// Unmarshal the entire configuration
	if err := v.Unmarshal(cfg); err != nil {
		return nil, fmt.Errorf("failed to unmarshal configuration: %w", err)
	}

	// Validate storage configuration
	if err := cfg.Validate(); err != nil {
		return nil, fmt.Errorf("invalid configuration: %w", err)
	}

	return cfg, nil
}

// Validate validates the configuration.
func (c *Config) Validate() error {
	// Validate storage configuration
	if err := c.Storage.Validate(); err != nil {
		return err
	}

	// Ensure only one backend is defined for remote-storage
	if len(c.Storage.TraceBackends) > 1 {
		return fmt.Errorf("remote-storage only supports a single storage backend, but %d were configured", len(c.Storage.TraceBackends))
	}

	return nil

View on GitHub (pinned to 806f444784)

Solutions

  1. Read the wrapped inner error to see which validation rule failed
  2. Ensure at most one backend is defined under storage.trace_backends (remote-storage is single-backend)
  3. Ensure the single backend entry includes its required type-specific block (e.g. `memory:` or `cassandra:`)
  4. Run with the DefaultConfig-style structure as a reference and adjust field-by-field

Example fix

// before
storage:
  trace_backends:
    memory: {memory: {max_traces: 1000000}}
    cassandra: {cassandra: {servers: [cassandra:9042]}}
// after
storage:
  trace_backends:
    cassandra: {cassandra: {servers: [cassandra:9042]}}
Defensive patterns

Strategy: validation

Validate before calling

backends := v.GetStringMap("storage.trace_backends")
if len(backends) > 1 {
    return fmt.Errorf("remote-storage supports one backend, got %d", len(backends))
}
if len(backends) == 1 {
    for name, cfgAny := range backends {
        m, ok := cfgAny.(map[string]any)
        if !ok || len(m) == 0 {
            return fmt.Errorf("backend %q has empty configuration", name)
        }
    }
}

Try / catch

cfg, err := app.LoadConfigFromViper(v)
if err != nil {
    if strings.Contains(err.Error(), "invalid configuration") {
        // semantic validation failed; inspect wrapped cause for the rule
        fmt.Fprintf(os.Stderr, "config rejected: %v\n", err)
        os.Exit(1)
    }
    return err
}

Prevention

When it happens

Trigger: Calling LoadConfigFromViper with structurally valid YAML that fails cfg.Validate(): e.g. two entries under storage.trace_backends, or a backend entry violating the storage config's own validation rules (missing required fields for the declared backend type).

Common situations: Copying the main `jaeger` binary's multi-backend storage config into remote-storage; defining both a memory and a cassandra backend; leaving a backend entry empty/missing its type-specific configuration block.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/8d68e1d721219b1c. Report an issue: GitHub.