grpc/grpc-go · error
error parsing observability config
Error message
error parsing observability config: %v
What it means
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.
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.
Example fix
// before
export GRPC_GCP_OBSERVABILITY_CONFIG='{"cloud_trace": {sampling_rate: 0.1}}'
// after
export GRPC_GCP_OBSERVABILITY_CONFIG='{"cloud_trace":{"sampling_rate":0.1}}' Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate JSON before pointing the env var at it.
func validateConfigJSON(b []byte) error {
var c struct {
ProjectID string `json:"project_id"`
CloudLogging *json.RawMessage `json:"cloud_logging"`
CloudMonitoring *json.RawMessage `json:"cloud_monitoring"`
CloudTrace *struct {
SamplingRate float64 `json:"sampling_rate"`
} `json:"cloud_trace"`
Labels map[string]string `json:"labels"`
}
return json.Unmarshal(b, &c)
}
if err := validateConfigJSON(rawConfig); err != nil { return err } Try / catch
if err := observability.Start(ctx); err != nil {
if strings.Contains(err.Error(), "error parsing observability config") && !strings.Contains(err.Error(), "sampling rate") {
// likely JSON syntax; surface the inner json error
return fmt.Errorf("observability config JSON invalid: %w", err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- cannot have a leading slash
- cannot have exclude and a '*' wildcard
- empty destination project ID
- error in clientRPCEvent method
- error in serverRPCEvent method
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/8291c3100b3a8bbf.
Report an issue: GitHub.
Appendix: source
Thrown at gcp/observability/config.go:114
if err := validateLogEventMethod(clientRPCEvent.Methods, clientRPCEvent.Exclude); err != nil {
return fmt.Errorf("error in clientRPCEvent method: %v", err)
}
}
for _, serverRPCEvent := range config.CloudLogging.ServerRPCEvents {
if err := validateLogEventMethod(serverRPCEvent.Methods, serverRPCEvent.Exclude); err != nil {
return fmt.Errorf("error in serverRPCEvent method: %v", err)
}
}
return nil
}
// unmarshalAndVerifyConfig unmarshals a json string representing an
// observability config into its internal go format, and also verifies the
// configuration's fields for validity.
func unmarshalAndVerifyConfig(rawJSON json.RawMessage) (*config, error) {
var config config
if err := json.Unmarshal(rawJSON, &config); err != nil {
return nil, fmt.Errorf("error parsing observability config: %v", err)
}
if err := validateLoggingEvents(&config); err != nil {
return nil, fmt.Errorf("error parsing observability config: %v", err)
}
if config.CloudTrace != nil && (config.CloudTrace.SamplingRate > 1 || config.CloudTrace.SamplingRate < 0) {
return nil, fmt.Errorf("error parsing observability config: invalid cloud trace sampling rate %v", config.CloudTrace.SamplingRate)
}
logger.Infof("Parsed ObservabilityConfig: %+v", &config)
return &config, nil
}
func parseObservabilityConfig() (*config, error) {
if f := envconfig.ObservabilityConfigFile; f != "" {
if envconfig.ObservabilityConfig != "" {
logger.Warning("Ignoring GRPC_GCP_OBSERVABILITY_CONFIG and using GRPC_GCP_OBSERVABILITY_CONFIG_FILE contents.")
}
content, err := os.ReadFile(f)
if err != nil {View on GitHub (pinned to 0c51461d27)