pulumi/pulumi · error

failed to connect to OTLP collector: %w

Error message

failed to connect to OTLP collector: %w

What it means

The gRPC span exporter establishes a client connection to an OTLP collector with grpc.NewClient using the configured target address. If the client cannot be constructed — invalid endpoint syntax, unsupported scheme, or bad dial options — this wrapped error is returned and the receiver fails to start.

Source

Thrown at sdk/go/common/util/otelreceiver/grpc_exporter.go:62

	headers map[string]string
}

func newGRPCExporterWithOptions(opts grpcExporterOptions) (*GRPCExporter, error) {
	target := strings.TrimPrefix(opts.target, "grpc://")
	target = strings.TrimPrefix(target, "grpcs://")

	var dialOpts []grpc.DialOption
	if opts.tls {
		dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
			MinVersion: tls.VersionTLS12,
		})))
	} else {
		dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	}

	conn, err := grpc.NewClient(target, dialOpts...)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to OTLP collector: %w", err)
	}

	var md metadata.MD
	if len(opts.headers) > 0 {
		md = metadata.New(opts.headers)
	}

	return &GRPCExporter{
		conn:    conn,
		client:  coltracepb.NewTraceServiceClient(conn),
		headers: md,
	}, nil
}

func (e *GRPCExporter) ExportSpans(ctx context.Context, spans []*tracepb.ResourceSpans) error {
	if len(spans) == 0 {
		return nil
	}

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Validate the target is a valid host:port or accepted grpc target (strip http:// or https:// scheme prefixes)
  2. Confirm the collector address and port, e.g. test with `grpcurl -plaintext host:4317`
  3. Check TLS settings: if the endpoint expects TLS, don't pass insecure credentials, and vice versa
  4. Log the wrapped inner error (%w) for the precise grpc parser message

Example fix

// before
exporter, err := newGRPCExporter(ctx, "http://localhost:4317", opts)
// after
exporter, err := newGRPCExporter(ctx, "localhost:4317", opts)
Defensive patterns

Strategy: validation

Validate before calling

// validate a gRPC target before handing it to the exporter
u, err := url.Parse(endpoint)
valid := err == nil && (u.Scheme == "" && net.ParseIP(u.Hostname()) != nil ||
    u.Scheme == "dns" || u.Scheme == "passthrough") && u.Port() != ""

Prevention

When it happens

Trigger: otelreceiver.Start is called with a gRPC exporter whose target string is malformed (e.g. 'localhost:xyz', empty, or an unparseable scheme like 'unix://'), or with dial options that grpc.NewClient rejects (invalid TLS credentials configuration).

Common situations: Typos in the PULUMI_OTEL_EXPORTER_OTLP_ENDPOINT-style env var; passing a URL ('http://host:4317') where a bare host:port is expected; bad custom endpoint from a self-hosted collector config; DNS/unix socket schemes the grpc resolver cannot handle.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/18926e508ba87aa7. Report an issue: GitHub.