{"record":{"id":"7d05ae019ba20181","repo":"grafana/k6","slug":"http-exporter-endpoint-must-only-be-host-and-port","errorCode":null,"errorMessage":"HTTP exporter endpoint must only be host and port, no scheme","messagePattern":"HTTP exporter endpoint must only be host and port, no scheme","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/output/opentelemetry/config.go","lineNumber":246,"sourceCode":"\t\t\t\tcfg.ExporterProtocol.String,\n\t\t\t\tgrpcExporterProtocol,\n\t\t\t\thttpExporterProtocol,\n\t\t\t)\n\t\t}\n\t\tswitch cfg.ExporterProtocol.String {\n\t\tcase grpcExporterProtocol:\n\t\t\tif cfg.GRPCExporterEndpoint.String == \"\" {\n\t\t\t\treturn errors.New(\"gRPC exporter endpoint is required\")\n\t\t\t}\n\t\tcase httpExporterProtocol:\n\t\t\tendpoint := cfg.HTTPExporterEndpoint.String\n\t\t\tif endpoint == \"\" {\n\t\t\t\treturn errors.New(\"HTTP exporter endpoint is required\")\n\t\t\t}\n\n\t\t\tif strings.HasPrefix(endpoint, \"http://\") ||\n\t\t\t\tstrings.HasPrefix(endpoint, \"https://\") {\n\t\t\t\treturn errors.New(\"HTTP exporter endpoint must only be host and port, no scheme\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// String returns a string representation of the config\nfunc (cfg Config) String() string {\n\tvar endpoint string\n\tprotocol := cfg.ExporterProtocol.String\n\tswitch protocol {\n\tcase httpExporterProtocol:\n\t\tendpoint = \"http\"\n\t\tif !cfg.HTTPExporterInsecure.Bool {\n\t\t\tendpoint += \"s\"\n\t\t}\n\t\tendpoint += \"://\" + cfg.HTTPExporterEndpoint.String + cfg.HTTPExporterURLPath.String\n\tcase grpcExporterProtocol:","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/output/opentelemetry/config.go#L228-L264","documentation":"Thrown by Config.validateExporterProtocol() when the HTTP exporter endpoint starts with http:// or https://. The OTLP HTTP exporter option expects host[:port] and applies its own scheme/insecure logic (httpExporterInsecure), so an embedded scheme would produce a malformed URL and is rejected up front.","triggerScenarios":"Setting K6_OTEL_HTTP_EXPORTER_ENDPOINT=https://collector.example.com:4318 or http://localhost:4318 while exporterProtocol is http/protobuf; copying a full collector URL from documentation or a browser into the env var; JSON config with a fully-qualified URL in httpExporterEndpoint.","commonSituations":"Users pasting the collector's web URL; mixing conventions with Prometheus remote write (-o prometheus-rw) where URLs are expected; confusion after switching from OTLP/HTTP gateway examples that show scheme-prefixed URLs.","solutions":["Strip the scheme: K6_OTEL_HTTP_EXPORTER_ENDPOINT=collector.example.com:4318","For plain HTTP to a local collector, keep the bare host:port and set K6_OTEL_HTTP_EXPORTER_INSECURE=true if TLS must not be attempted","Update any config templates that store the full URL and derive the bare endpoint from it"],"exampleFix":"# before\nexport K6_OTEL_HTTP_EXPORTER_ENDPOINT=http://localhost:4318\n\n# after\nexport K6_OTEL_HTTP_EXPORTER_ENDPOINT=localhost:4318\nexport K6_OTEL_HTTP_EXPORTER_INSECURE=true","handlingStrategy":"validation","validationCode":"case \"$K6_OTEL_HTTP_EXPORTER_ENDPOINT\" in\n  http://*|https://*) echo \"endpoint must be host:port without scheme\"; exit 1;;\nesac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store collector endpoints as host:port in your config store, not full URLs","If a full URL is the source of truth, strip the scheme in the wrapper before exporting","Remember K6_OTEL_HTTP_EXPORTER_INSECURE=true replaces http:// for plain-text collectors"],"tags":["k6","opentelemetry","otlp","endpoint","url-format","config"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}