{"record":{"id":"7a607d2caee9c0e1","repo":"grafana/k6","slug":"unsupported-exporter-protocol-s","errorCode":null,"errorMessage":"unsupported exporter protocol %s","messagePattern":"unsupported exporter protocol (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/output/opentelemetry/exporter.go","lineNumber":54,"sourceCode":"\t\theaders, err = parseHeaders(cfg.Headers.String)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse headers: %w\", err)\n\t\t}\n\t}\n\n\t// if at least valid user was configured, use basic auth\n\tif cfg.HTTPUsername.Valid {\n\t\tauth := []byte(cfg.HTTPUsername.String + \":\" + cfg.HTTPPassword.String)\n\t\theaders[\"Authorization\"] = fmt.Sprintf(\"Basic %s\", base64.StdEncoding.EncodeToString(auth))\n\t}\n\n\tswitch cfg.ExporterProtocol.String {\n\tcase grpcExporterProtocol:\n\t\treturn buildGRPCExporter(ctx, cfg, tlsConfig, headers)\n\tcase httpExporterProtocol:\n\t\treturn buildHTTPExporter(ctx, cfg, tlsConfig, headers)\n\tdefault:\n\t\treturn nil, errors.New(\"unsupported exporter protocol \" + cfg.ExporterProtocol.String)\n\t}\n}\n\nfunc buildHTTPExporter(\n\tctx context.Context,\n\tcfg Config,\n\ttlsConfig *tls.Config,\n\theaders map[string]string,\n) (metric.Exporter, error) {\n\topts := []otlpmetrichttp.Option{\n\t\totlpmetrichttp.WithEndpoint(cfg.HTTPExporterEndpoint.String),\n\t\totlpmetrichttp.WithURLPath(cfg.HTTPExporterURLPath.String),\n\t}\n\n\tif cfg.HTTPExporterInsecure.Bool {\n\t\topts = append(opts, otlpmetrichttp.WithInsecure())\n\t}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/output/opentelemetry/exporter.go#L36-L72","documentation":"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.","triggerScenarios":"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.","commonSituations":"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').","solutions":["Use exactly one of: grpc, http/protobuf for exporterProtocol","If embedding k6, call Config.Validate() before building the exporter so the descriptive error from config.go is returned instead","Trim whitespace and normalize casing before assigning the protocol value"],"exampleFix":"# before\nexport K6_OTEL_EXPORTER_PROTOCOL=http\n\n# after\nexport K6_OTEL_EXPORTER_PROTOCOL=http/protobuf","handlingStrategy":"validation","validationCode":"// Go embedders: validate before building the exporter.\nallowedProtocols := map[string]bool{\"grpc\": true, \"http/protobuf\": true}\nif !allowedProtocols[cfg.ExporterProtocol.String] {\n    return fmt.Errorf(\"unsupported exporter protocol %q\", cfg.ExporterProtocol.String)\n}\n_ = cfg.Validate() // run the full config validation first","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["Always call Config.Validate() before building the OTel exporter when embedding k6","Use exactly 'grpc' or 'http/protobuf'; no other casing or alias is accepted","Add a config lint in CI that rejects any other exporterProtocol value"],"tags":["k6","opentelemetry","otlp","protocol","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}