{"record":{"id":"8291c3100b3a8bbf","repo":"grpc/grpc-go","slug":"error-parsing-observability-config-v","errorCode":null,"errorMessage":"error parsing observability config: %v","messagePattern":"error parsing observability config: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gcp/observability/config.go","lineNumber":114,"sourceCode":"\t\tif err := validateLogEventMethod(clientRPCEvent.Methods, clientRPCEvent.Exclude); err != nil {\n\t\t\treturn fmt.Errorf(\"error in clientRPCEvent method: %v\", err)\n\t\t}\n\t}\n\tfor _, serverRPCEvent := range config.CloudLogging.ServerRPCEvents {\n\t\tif err := validateLogEventMethod(serverRPCEvent.Methods, serverRPCEvent.Exclude); err != nil {\n\t\t\treturn fmt.Errorf(\"error in serverRPCEvent method: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// unmarshalAndVerifyConfig unmarshals a json string representing an\n// observability config into its internal go format, and also verifies the\n// configuration's fields for validity.\nfunc unmarshalAndVerifyConfig(rawJSON json.RawMessage) (*config, error) {\n\tvar config config\n\tif err := json.Unmarshal(rawJSON, &config); err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing observability config: %v\", err)\n\t}\n\tif err := validateLoggingEvents(&config); err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing observability config: %v\", err)\n\t}\n\tif config.CloudTrace != nil && (config.CloudTrace.SamplingRate > 1 || config.CloudTrace.SamplingRate < 0) {\n\t\treturn nil, fmt.Errorf(\"error parsing observability config: invalid cloud trace sampling rate %v\", config.CloudTrace.SamplingRate)\n\t}\n\tlogger.Infof(\"Parsed ObservabilityConfig: %+v\", &config)\n\treturn &config, nil\n}\n\nfunc parseObservabilityConfig() (*config, error) {\n\tif f := envconfig.ObservabilityConfigFile; f != \"\" {\n\t\tif envconfig.ObservabilityConfig != \"\" {\n\t\t\tlogger.Warning(\"Ignoring GRPC_GCP_OBSERVABILITY_CONFIG and using GRPC_GCP_OBSERVABILITY_CONFIG_FILE contents.\")\n\t\t}\n\t\tcontent, err := os.ReadFile(f)\n\t\tif err != nil {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/gcp/observability/config.go#L96-L132","documentation":"The observability config JSON failed to unmarshal into the internal config struct. encoding/json rejected the document before any field validation ran, so the wrapped error is a json error (syntax error, type mismatch, unknown field with DisallowUnknownFields-style failure). Emitted at config.go:114 inside unmarshalAndVerifyConfig.","triggerScenarios":"Passing GRPC_GCP_OBSERVABILITY_CONFIG an invalid JSON string, or pointing GRPC_GCP_OBSERVABILITY_CONFIG_FILE at a file whose contents are not valid JSON for the config schema. Common json errors: trailing comma, single quotes, unquoted keys, a string where a number/object is expected (e.g. sampling_rate as a string).","commonSituations":"Hand-writing the config JSON; templating it with envsubst so '$' characters corrupt values; YAML mistakenly used instead of JSON; a stray BOM or comment block; field renamed across grpc-go versions leaving an unknown key.","solutions":["Copy the config string/file out and run it through `jq .` (or `python -m json.tool`) to surface the exact JSON syntax error.","Compare your keys against the documented schema: project_id, cloud_logging, cloud_monitoring, cloud_trace, labels.","Remove comments (JSON has none), use double quotes, and ensure numbers (sampling_rate) are unquoted.","If using a template engine, render it to a file and validate the result before pointing GRPC_GCP_OBSERVABILITY_CONFIG_FILE at it."],"exampleFix":"// before\nexport GRPC_GCP_OBSERVABILITY_CONFIG='{\"cloud_trace\": {sampling_rate: 0.1}}'\n\n// after\nexport GRPC_GCP_OBSERVABILITY_CONFIG='{\"cloud_trace\":{\"sampling_rate\":0.1}}'","handlingStrategy":"validation","validationCode":"// Pre-validate JSON before pointing the env var at it.\nfunc validateConfigJSON(b []byte) error {\n    var c struct {\n        ProjectID      string                 `json:\"project_id\"`\n        CloudLogging   *json.RawMessage       `json:\"cloud_logging\"`\n        CloudMonitoring *json.RawMessage      `json:\"cloud_monitoring\"`\n        CloudTrace     *struct {\n            SamplingRate float64 `json:\"sampling_rate\"`\n        } `json:\"cloud_trace\"`\n        Labels map[string]string `json:\"labels\"`\n    }\n    return json.Unmarshal(b, &c)\n}\n\nif err := validateConfigJSON(rawConfig); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := observability.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"error parsing observability config\") && !strings.Contains(err.Error(), \"sampling rate\") {\n        // likely JSON syntax; surface the inner json error\n        return fmt.Errorf(\"observability config JSON invalid: %w\", err)\n    }\n    return err\n}","preventionTips":["Run the config through `jq .` before deploying.","Generate the config from a typed struct via json.Marshal rather than hand-writing it.","Disallow comments and single-quoted strings in the templating layer."],"tags":["observability","config","json","parsing"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}