{"record":{"id":"c9008dcde8bcd8ba","repo":"grpc/grpc-go","slug":"empty-destination-project-id","errorCode":null,"errorMessage":"empty destination project ID","messagePattern":"empty destination project ID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gcp/observability/config.go","lineNumber":148,"sourceCode":"\t\t}\n\t\tcontent, err := os.ReadFile(f)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading observability configuration file %q: %v\", f, err)\n\t\t}\n\t\treturn unmarshalAndVerifyConfig(content)\n\t} else if envconfig.ObservabilityConfig != \"\" {\n\t\treturn unmarshalAndVerifyConfig([]byte(envconfig.ObservabilityConfig))\n\t}\n\t// If the ENV var doesn't exist, do nothing\n\treturn nil, nil\n}\n\nfunc ensureProjectIDInObservabilityConfig(ctx context.Context, config *config) error {\n\tif config.ProjectID == \"\" {\n\t\t// Try to fetch the GCP project id\n\t\tprojectID := fetchDefaultProjectID(ctx)\n\t\tif projectID == \"\" {\n\t\t\treturn fmt.Errorf(\"empty destination project ID\")\n\t\t}\n\t\tconfig.ProjectID = projectID\n\t}\n\treturn nil\n}\n\ntype clientRPCEvents struct {\n\t// Methods is a list of strings which can select a group of methods. By\n\t// default, the list is empty, matching no methods.\n\t//\n\t// The value of the method is in the form of <service>/<method>.\n\t//\n\t// \"*\" is accepted as a wildcard for:\n\t//    1. The method name. If the value is <service>/*, it matches all\n\t//    methods in the specified service.\n\t//    2. The whole value of the field which matches any <service>/<method>.\n\t//    It’s not supported when Exclude is true.\n\t//    3. The * wildcard cannot be used on the service name independently,","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/gcp/observability/config.go#L130-L166","documentation":"The config has no project_id and neither the GOOGLE_CLOUD_PROJECT env var nor the GCP default credential exposes a project. Cloud Logging/Trace/Monitoring all need a destination project, so ensureProjectIDInObservabilityConfig refuses to continue. Emitted at config.go:148.","triggerScenarios":"Calling observability.Start where config.project_id is empty AND GOOGLE_CLOUD_PROJECT is unset AND google.FindDefaultCredentials either failed or returned credentials with an empty ProjectID. Common on developer laptops, on-prem, or CI outside GCP metadata.","commonSituations":"Running locally without `gcloud auth application-default login`; service account JSON key without a project; workload running outside GCE/GKE/Cloud Run metadata; env var renamed (e.g. GCLOUD_PROJECT instead of GOOGLE_CLOUD_PROJECT); ADC scoped to a non-project resource.","solutions":["Set \"project_id\" in the observability config JSON to your GCP project.","Or export GOOGLE_CLOUD_PROJECT=<your-project> in the process environment.","Or run `gcloud auth application-default login` so ADC carries a project_id.","If using a service-account key JSON, ensure it has a \"project_id\" field and that GOOGLE_APPLICATION_CREDENTIALS points to it.","On GCE/GKE/Cloud Run the metadata server usually supplies this automatically — verify metadata connectivity if missing."],"exampleFix":"// before\nexport GRPC_GCP_OBSERVABILITY_CONFIG='{\"cloud_logging\":{}}'\n\n// after\nexport GRPC_GCP_OBSERVABILITY_CONFIG='{\"project_id\":\"my-proj\",\"cloud_logging\":{}}'\n# or\nexport GOOGLE_CLOUD_PROJECT=my-proj","handlingStrategy":"validation","validationCode":"func resolveProjectID() (string, error) {\n    if p := os.Getenv(\"GOOGLE_CLOUD_PROJECT\"); p != \"\" { return p, nil }\n    creds, err := google.FindDefaultCredentials(context.Background(), gcplogging.WriteScope)\n    if err != nil || creds.ProjectID == \"\" {\n        return \"\", errors.New(\"no project_id: set config.project_id or GOOGLE_CLOUD_PROJECT or run `gcloud auth application-default login`\")\n    }\n    return creds.ProjectID, nil\n}\n\nif _, err := resolveProjectID(); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := observability.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"empty destination project ID\") {\n        return fmt.Errorf(\"set project_id in config or GOOGLE_CLOUD_PROJECT, or provision ADC: %w\", err)\n    }\n    return err\n}","preventionTips":["Always pin project_id in the config for non-GCP environments.","Set GOOGLE_CLOUD_PROJECT in your container base image.","Validate ADC project availability in a startup probe."],"tags":["observability","config","gcp","project-id"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}