{"record":{"id":"f581d7a5ae579e70","repo":"thanos-io/thanos","slug":"level-field-is-empty","errorCode":null,"errorMessage":"level field is empty","messagePattern":"level field is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/logging/grpc.go","lineNumber":33,"sourceCode":"\n// NewRequestConfig parses the string into a req logging config structure.\n// Raise an error if unmarshalling is not possible, or values are not valid.\nfunc NewRequestConfig(configYAML []byte) (*RequestConfig, error) {\n\treqLogConfig := &RequestConfig{}\n\tif err := yaml.UnmarshalStrict(configYAML, reqLogConfig); err != nil {\n\t\treturn nil, err\n\t}\n\treturn reqLogConfig, nil\n}\n\n// checkOptionsConfigEmpty checks if the OptionsConfig struct is empty and valid.\n// If invalid combination is present, return an error.\nfunc checkOptionsConfigEmpty(optcfg OptionsConfig) (bool, error) {\n\tif optcfg.Level == \"\" && !optcfg.Decision.LogEnd && !optcfg.Decision.LogStart {\n\t\treturn true, nil\n\t}\n\tif optcfg.Level == \"\" && (optcfg.Decision.LogStart || optcfg.Decision.LogEnd) {\n\t\treturn false, fmt.Errorf(\"level field is empty\")\n\t}\n\treturn false, nil\n}\n\n// fillGlobalOptionConfig configures all the method to have global config for logging.\nfunc fillGlobalOptionConfig(reqLogConfig *RequestConfig, isgRPC bool) (string, bool, bool, error) {\n\tglobalLevel := \"ERROR\"\n\tglobalStart, globalEnd := false, false\n\n\tglobalOptionConfig := reqLogConfig.Options\n\tisEmpty, err := checkOptionsConfigEmpty(globalOptionConfig)\n\n\t// If the decision for logging is enabled with empty level field.\n\tif err != nil {\n\t\treturn \"\", false, false, err\n\t}\n\tif !isEmpty {\n\t\tglobalLevel = globalOptionConfig.Level","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/logging/grpc.go#L15-L51","documentation":"checkOptionsConfigEmpty validates gRPC logging interceptor options: a config is fully empty only if no level is set AND neither LogStart nor LogEnd is requested. If a log decision (LogStart or LogEnd) is requested but the level field is empty, the configuration is contradictory and this error is raised.","triggerScenarios":"Creating gRPC logging options from YAML where a decision like logStart: true or logEnd: true is set but the 'level' field is omitted or empty string.","commonSituations":"Partially filled logging config blocks in the gRPC server options YAML; users setting log decisions under a different config key than 'level'.","solutions":["Set the 'level' field in the logging config (INFO/DEBUG/ERROR/WARNING).","If no logging is wanted, remove the logStart/logEnd decisions instead of leaving level empty.","Validate the YAML block before applying it with NewGRPCOption."],"exampleFix":"// before\ngrpc:\n  - logStart: true\n// after\ngrpc:\n  - level: INFO\n    logStart: true","handlingStrategy":"validation","validationCode":"if (decision.LogStart || decision.LogEnd) && level == \"\" {\n  return fmt.Errorf(\"level must be set when logStart/logEnd is enabled\")\n}","typeGuard":null,"tryCatchPattern":"opt, err := logging.NewGRPCOption(cfg)\nif err != nil { return fmt.Errorf(\"invalid gRPC logging config: %w\", err) }","preventionTips":["Always pair log decisions with a level in YAML","Render logging config from a schema-validated template","Test config load in CI before deploy"],"tags":["grpc","logging","config-validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}