{"record":{"id":"0be5acf756aa0c20","repo":"grpc/grpc-go","slug":"no-observabilityconfig-found","errorCode":null,"errorMessage":"no ObservabilityConfig found","messagePattern":"no ObservabilityConfig found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gcp/observability/observability.go","lineNumber":54,"sourceCode":"\n// Start is the opt-in API for gRPC Observability plugin. This function should\n// be invoked in the main function, and before creating any gRPC clients or\n// servers, otherwise, they might not be instrumented. At high-level, this\n// module does the following:\n//\n//   - it loads observability config from environment;\n//   - it registers default exporters if not disabled by the config;\n//   - it sets up telemetry collectors (binary logging sink or StatsHandlers).\n//\n// Note: this method should only be invoked once.\n// Note: handle the error\nfunc Start(ctx context.Context) error {\n\tconfig, err := parseObservabilityConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif config == nil {\n\t\treturn fmt.Errorf(\"no ObservabilityConfig found\")\n\t}\n\n\t// Set the project ID if it isn't configured manually.\n\tif err = ensureProjectIDInObservabilityConfig(ctx, config); err != nil {\n\t\treturn err\n\t}\n\n\t// Cleanup any created resources this function created in case this function\n\t// errors.\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tEnd()\n\t\t}\n\t}()\n\n\t// Enabling tracing and metrics via OpenCensus\n\tif err = startOpenCensus(config); err != nil {\n\t\treturn fmt.Errorf(\"failed to instrument OpenCensus: %v\", err)","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/gcp/observability/observability.go#L36-L72","documentation":"Returned by observability.Start(ctx) when parseObservabilityConfig() succeeds but yields a nil config. The observability plugin is opt-in and expects configuration to be supplied (via the CLOUD_OBSERVABILITY_CONFIG env var or equivalent), so a parsed-but-nil result means the user invoked Start() without providing any observability config. It is a hard startup failure: nothing is instrumented.","triggerScenarios":"Calling observability.Start(ctx) in main() without setting the CLOUD_OBSERVABILITY_CONFIG environment variable (or with it set to an empty/blank value). Also when the env var is present but maps to a config object that resolves to nil because no tracing, logging, or monitoring section was enabled.","commonSituations":"Copy-pasting a Start() call from a sample without shipping the config env var; running the same binary in a new environment (CI, fresh container) that lacks the exported variable; enabling observability behind a feature flag that is off.","solutions":["Set the CLOUD_OBSERVABILITY_CONFIG environment variable to a valid JSON config string before invoking Start().","If you do not want observability, remove the observability.Start(ctx) call rather than letting it run unconfigured.","Verify the config is exported in your container/process spec (Docker ENV, Kubernetes env, systemd Environment=).","Log the parsed config at debug level to confirm the env var is actually read by the process."],"exampleFix":"// before\nfunc main() {\n    _ = observability.Start(ctx) // returns \"no ObservabilityConfig found\"\n}\n// after\nfunc main() {\n    // CLOUD_OBSERVABILITY_CONFIG set in the environment:\n    // {\"cloud_logging\":{},\"cloud_trace\":{\"sampling_rate\":1.0},\"cloud_monitoring\":{}}\n    if err := observability.Start(ctx); err != nil {\n        log.Fatalf(\"observability start failed: %v\", err)\n    }\n    defer observability.End()\n}","handlingStrategy":"validation","validationCode":"// Fail fast before Start() if no config is present.\nif os.Getenv(\"CLOUD_OBSERVABILITY_CONFIG\") == \"\" {\n    log.Println(\"observability disabled: CLOUD_OBSERVABILITY_CONFIG unset\")\n} else if err := observability.Start(ctx); err != nil {\n    log.Fatalf(\"observability.Start: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := observability.Start(ctx); err != nil {\n    // observability is opt-in; treat a missing-config error as non-fatal and proceed without telemetry.\n    log.Printf(\"observability not started: %v\", err)\n}","preventionTips":["Document the required CLOUD_OBSERVABILITY_CONFIG env var in your deployment manifest.","Gate the Start() call behind an explicit enable flag rather than calling it unconditionally.","Add a startup smoke test asserting the env var is set in observability-enabled environments."],"tags":["grpc","observability","configuration","environment","gcp","startup"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}