grafana/k6 · error

unsupported exporter protocol %s

Error message

unsupported exporter protocol %s

What it means

Returned by the OpenTelemetry output's exporter builder when cfg.ExporterProtocol.String matches neither the gRPC nor the http/protobuf constants. It is the defensive default branch behind the builder's switch; in practice Config.Validate() should have already rejected the value, so seeing it means a code path built an exporter with an unvalidated config.

Source

Thrown at internal/output/opentelemetry/exporter.go:54

		headers, err = parseHeaders(cfg.Headers.String)
		if err != nil {
			return nil, fmt.Errorf("failed to parse headers: %w", err)
		}
	}

	// if at least valid user was configured, use basic auth
	if cfg.HTTPUsername.Valid {
		auth := []byte(cfg.HTTPUsername.String + ":" + cfg.HTTPPassword.String)
		headers["Authorization"] = fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(auth))
	}

	switch cfg.ExporterProtocol.String {
	case grpcExporterProtocol:
		return buildGRPCExporter(ctx, cfg, tlsConfig, headers)
	case httpExporterProtocol:
		return buildHTTPExporter(ctx, cfg, tlsConfig, headers)
	default:
		return nil, errors.New("unsupported exporter protocol " + cfg.ExporterProtocol.String)
	}
}

func buildHTTPExporter(
	ctx context.Context,
	cfg Config,
	tlsConfig *tls.Config,
	headers map[string]string,
) (metric.Exporter, error) {
	opts := []otlpmetrichttp.Option{
		otlpmetrichttp.WithEndpoint(cfg.HTTPExporterEndpoint.String),
		otlpmetrichttp.WithURLPath(cfg.HTTPExporterURLPath.String),
	}

	if cfg.HTTPExporterInsecure.Bool {
		opts = append(opts, otlpmetrichttp.WithInsecure())
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use exactly one of: grpc, http/protobuf for exporterProtocol
  2. If embedding k6, call Config.Validate() before building the exporter so the descriptive error from config.go is returned instead
  3. Trim whitespace and normalize casing before assigning the protocol value

Example fix

# before
export K6_OTEL_EXPORTER_PROTOCOL=http

# after
export K6_OTEL_EXPORTER_PROTOCOL=http/protobuf
Defensive patterns

Strategy: validation

Validate before calling

// Go embedders: validate before building the exporter.
allowedProtocols := map[string]bool{"grpc": true, "http/protobuf": true}
if !allowedProtocols[cfg.ExporterProtocol.String] {
    return fmt.Errorf("unsupported exporter protocol %q", cfg.ExporterProtocol.String)
}
_ = cfg.Validate() // run the full config validation first

Try / catch

In Go, wrap exporter construction and compare with errors.Is against the unsupported-protocol error, then surface the validated config's message which names the two allowed values.

Prevention

When it happens

Trigger: Embedding k6 as a library and calling the output's exporter construction with a Config that skipped Validate(); typos in exporterProtocol such as 'http' instead of 'http/protobuf', 'HTTP', or 'grpc '; passing a protocol string through a custom wrapper that mutates it after validation.

Common situations: xk6 extensions building the OTel output directly; forks of k6 that bypass validation; values copied from other tools' config dialects (e.g. Jaeger exporters use 'http-thrift').

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/7a607d2caee9c0e1. Report an issue: GitHub.