grpc/grpc-go · error

empty destination project ID

Error message

empty destination project ID

What it means

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.

Solutions

  1. Set "project_id" in the observability config JSON to your GCP project.
  2. Or export GOOGLE_CLOUD_PROJECT=<your-project> in the process environment.
  3. Or run `gcloud auth application-default login` so ADC carries a project_id.
  4. If using a service-account key JSON, ensure it has a "project_id" field and that GOOGLE_APPLICATION_CREDENTIALS points to it.
  5. On GCE/GKE/Cloud Run the metadata server usually supplies this automatically — verify metadata connectivity if missing.

Example fix

// before
export GRPC_GCP_OBSERVABILITY_CONFIG='{"cloud_logging":{}}'

// after
export GRPC_GCP_OBSERVABILITY_CONFIG='{"project_id":"my-proj","cloud_logging":{}}'
# or
export GOOGLE_CLOUD_PROJECT=my-proj
Defensive patterns

Strategy: validation

Validate before calling

func resolveProjectID() (string, error) {
    if p := os.Getenv("GOOGLE_CLOUD_PROJECT"); p != "" { return p, nil }
    creds, err := google.FindDefaultCredentials(context.Background(), gcplogging.WriteScope)
    if err != nil || creds.ProjectID == "" {
        return "", errors.New("no project_id: set config.project_id or GOOGLE_CLOUD_PROJECT or run `gcloud auth application-default login`")
    }
    return creds.ProjectID, nil
}

if _, err := resolveProjectID(); err != nil { return err }

Try / catch

if err := observability.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "empty destination project ID") {
        return fmt.Errorf("set project_id in config or GOOGLE_CLOUD_PROJECT, or provision ADC: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/c9008dcde8bcd8ba. Report an issue: GitHub.

Appendix: source

Thrown at gcp/observability/config.go:148

		}
		content, err := os.ReadFile(f)
		if err != nil {
			return nil, fmt.Errorf("error reading observability configuration file %q: %v", f, err)
		}
		return unmarshalAndVerifyConfig(content)
	} else if envconfig.ObservabilityConfig != "" {
		return unmarshalAndVerifyConfig([]byte(envconfig.ObservabilityConfig))
	}
	// If the ENV var doesn't exist, do nothing
	return nil, nil
}

func ensureProjectIDInObservabilityConfig(ctx context.Context, config *config) error {
	if config.ProjectID == "" {
		// Try to fetch the GCP project id
		projectID := fetchDefaultProjectID(ctx)
		if projectID == "" {
			return fmt.Errorf("empty destination project ID")
		}
		config.ProjectID = projectID
	}
	return nil
}

type clientRPCEvents struct {
	// Methods is a list of strings which can select a group of methods. By
	// default, the list is empty, matching no methods.
	//
	// The value of the method is in the form of <service>/<method>.
	//
	// "*" is accepted as a wildcard for:
	//    1. The method name. If the value is <service>/*, it matches all
	//    methods in the specified service.
	//    2. The whole value of the field which matches any <service>/<method>.
	//    It’s not supported when Exclude is true.
	//    3. The * wildcard cannot be used on the service name independently,

View on GitHub (pinned to 0c51461d27)