{"record":{"id":"f7705487beb5d514","repo":"jaegertracing/jaeger","slug":"failed-to-unmarshal-configuration-w","errorCode":null,"errorMessage":"failed to unmarshal configuration: %w","messagePattern":"failed to unmarshal configuration: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/remote-storage/app/config.go","lineNumber":33,"sourceCode":"\t\"github.com/jaegertracing/jaeger/internal/tenancy\"\n)\n\n// Config represents the configuration for remote-storage service.\ntype Config struct {\n\tGRPC    configgrpc.ServerConfig `mapstructure:\"grpc\"`\n\tTenancy tenancy.Options         `mapstructure:\"multi_tenancy\"`\n\t// This configuration is the same as of the main `jaeger` binary,\n\t// but only one backend should be defined.\n\tStorage storageconfig.Config `mapstructure:\"storage\"`\n}\n\n// LoadConfigFromViper loads the configuration from Viper.\nfunc LoadConfigFromViper(v *viper.Viper) (*Config, error) {\n\tcfg := &Config{}\n\n\t// Unmarshal the entire configuration\n\tif err := v.Unmarshal(cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal configuration: %w\", err)\n\t}\n\n\t// Validate storage configuration\n\tif err := cfg.Validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid configuration: %w\", err)\n\t}\n\n\treturn cfg, nil\n}\n\n// Validate validates the configuration.\nfunc (c *Config) Validate() error {\n\t// Validate storage configuration\n\tif err := c.Storage.Validate(); err != nil {\n\t\treturn err\n\t}\n\n\t// Ensure only one backend is defined for remote-storage","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/remote-storage/app/config.go#L15-L51","documentation":"LoadConfigFromViper unmarshals the entire Viper state into the remote-storage Config struct (GRPC server, tenancy, storage backends). Viper's Unmarshal relies on mapstructure; when the YAML/env values cannot be decoded into the target fields (wrong types, unknown keys with strict decoding, bad nested structures) this error wraps and re-raises the decode failure.","triggerScenarios":"Calling LoadConfigFromViper with a viper instance whose settings do not match the Config schema — e.g. grpc port given as a string where a struct field is expected, multi_tenancy shaped incorrectly, or a storage backend field of the wrong type.","commonSituations":"Typo'd or misindented remote-storage config file; passing raw env vars of string type into numeric/struct fields; upgrading Jaeger where the storage config schema changed (single-backend `storage` layout) while using an old config; supplying full `jaeger` multi-backend storage config to the remote-storage binary.","solutions":["Read the wrapped mapstructure error — it names the exact field and expected type","Fix the YAML/env value type to match the Config struct (e.g. quote-free ints, correct nesting under grpc/multi_tenancy/storage)","Validate the config file against the current Jaeger version's remote-storage schema; migrate old keys","Start from the documented sample remote-storage config and re-apply your overrides"],"exampleFix":"# before\nstorage:\n  trace_backends: \"cassandra\"   # string, must be a map\n# after\nstorage:\n  trace_backends:\n    cassandra:\n      cassandra:\n        servers: [cassandra:9042]","handlingStrategy":"validation","validationCode":"func validateRemoteStorageKeys(v *viper.Viper) error {\n    for _, key := range []string{\"grpc\", \"storage\"} {\n        if v.Get(key) == nil { return fmt.Errorf(\"missing required section %q\", key) }\n    }\n    if _, ok := v.Get(\"storage.trace_backends\").(map[string]any); !ok {\n        return fmt.Errorf(\"storage.trace_backends must be a map of backend name -> config\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"cfg, err := app.LoadConfigFromViper(v)\nif err != nil {\n    var decodeErr mapstructure.Error\n    if errors.As(err, &decodeErr) {\n        for _, e := range decodeErr.Errors { fmt.Fprintln(os.Stderr, \"config: \", e) }\n    }\n    return fmt.Errorf(\"loading remote-storage config: %w\", err)\n}","preventionTips":["Lint remote-storage YAML against the current Jaeger schema","Match value types to struct fields (ints unquoted, maps not strings)","Migrate configs when upgrading Jaeger; the storage config layout changes between versions","Test config loading in CI with a LoadConfigFromViper smoke test"],"tags":["go","viper","configuration","remote-storage"],"backgroundTag":"config-unmarshal-failed","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}