{"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/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/output/opentelemetry/exporter.go#L36-L72","documentation":"The OTel metrics exporter builder dispatches on the configured protocol and only knows 'grpc' and 'http/protobuf' (k6's grpcExporterProtocol/httpExporterProtocol constants). Any other value reaches the default branch and fails at exporter construction. Note that the bare value 'http' is invalid — the HTTP protocol's full name is 'http/protobuf' — and even an empty string can reach here because Validate() skips its protocol check when the value is empty.","triggerScenarios":"K6_OTEL_EXPORTER_PROTOCOL=http (should be http/protobuf); proto=http/json (unsupported); an empty-string protocol override slipping past config validation; programmatic Config construction that skips GetConsolidatedConfig/Validate.","commonSituations":"Using OTel SDK spellings ('http', 'http/json') that k6 does not accept; empty env var overrides; wrappers building Config directly.","solutions":["Use exactly one of: grpc or http/protobuf","Check for an empty K6_OTEL_EXPORTER_PROTOCOL override and remove it so the grpc default applies","If you validate configs yourself, enforce the two allowed values before k6 constructs the exporter"],"exampleFix":"# before\nexport K6_OTEL_EXPORTER_PROTOCOL=http\nk6 run -o opentelemetry script.js\n# after\nexport K6_OTEL_EXPORTER_PROTOCOL=http/protobuf\nk6 run -o opentelemetry script.js","handlingStrategy":"validation","validationCode":"// Shell: allow-list the protocol\np=\"${K6_OTEL_EXPORTER_PROTOCOL:-grpc}\"\nif [ \"$p\" != \"grpc\" ] && [ \"$p\" != \"http/protobuf\" ]; then\n  echo \"K6_OTEL_EXPORTER_PROTOCOL must be grpc or http/protobuf\" >&2; exit 1\nfi","typeGuard":"function isSupportedOtelProtocol(p) {\n  return p === 'grpc' || p === 'http/protobuf';\n}","tryCatchPattern":null,"preventionTips":["Map OTel SDK spellings to k6's: http/protobuf (not http, not http/json)","Skip exporting the variable entirely when the grpc default is fine","Lint configs for protocol values outside the two supported names"],"tags":["opentelemetry","protocol","configuration","exporter","k6"],"backgroundTag":"unsupported-protocol","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}