A note for the community
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
Problem
Summary
The opentelemetry source's OTLP/HTTP endpoints only accept
Content-Type: application/x-protobuf. A request with
Content-Type: application/json — an encoding the OTLP/HTTP spec defines and
says servers SHOULD accept — is rejected with 500 Internal Server Error
and a binary body: a protobuf-encoded Status message whose text is the Rust
Debug dump of the internal warp rejection:
Rejection(InvalidHeader { name: "content-type" })
To a client this looks like a server crash, not an unsupported-media-type
condition.
Environment
- Vector 0.58.0 (
timberio/vector:0.58.0-debian); also reproduced on 0.55.0
opentelemetry source, default http config (address: 0.0.0.0:4318)
- Reproduced 2026-09-22;
src/sources/opentelemetry/http.rs is unchanged on
master as of that date
Steps to reproduce
vector --config /dev/stdin <<'EOF'
sources:
otlp:
type: opentelemetry
http:
address: 0.0.0.0:4318
sinks:
console:
type: console
inputs: [otlp.logs]
encoding: { codec: json }
EOF
curl -i -X POST http://localhost:4318/v1/logs \
-H "Content-Type: application/json" \
-d '{"resourceLogs":[{"scopeLogs":[{"logRecords":[{"timeUnixNano":"1790067000000000000","body":{"stringValue":"hello"},"severityText":"INFO"}]}]}]}'
Actual result
HTTP/1.1 500 Internal Server Error
content-type: application/x-protobuf
Body — 53 bytes of binary protobuf (hex):
0802 1231 5265 6a65 6374 696f 6e28 496e
7661 6c69 6448 6561 6465 7220 7b20 6e61
6d65 3a20 2263 6f6e 7465 6e74 2d74 7970
6522 207d 29
Decoded: field 1 (varint) = 2 (UNKNOWN), field 2 (string, 49 bytes) =
Rejection(InvalidHeader { name: "content-type" }) — the {:?} formatting
of the warp rejection, serialized into a Status message.
Control: the same request with Content-Type: application/x-protobuf (even
an empty body) returns 200 OK; the official OpenTelemetry SDK protobuf
exporter works on the first attempt.
Expected result
At minimum 415 Unsupported Media Type with a human-readable body naming the
unsupported content type. Ideally, full JSON support — the OTLP/HTTP spec
says:
Server implementations SHOULD accept OTLP/HTTP with binary-encoded
Protobuf payload and OTLP/HTTP with JSON-encoded Protobuf payload requests
on the same port and multiplex the requests to the corresponding payload
decoder based on the "Content-Type" request header.
— https://opentelemetry.io/docs/specs/otlp/#otlphttp
(The spec also requires the server to use the same Content-Type in the
response as it received in the request; the current response always
advertises application/x-protobuf.)
Root cause
src/sources/opentelemetry/http.rs:
-
The route filter requires the header exactly, so any other content type
fails the filter and becomes a warp Rejection (InvalidHeader):
.and(warp::header::exact_ignore_case(
"content-type",
"application/x-protobuf",
))
-
handle_rejection (the .recover() handler) treats every rejection that
is not the source's own ErrorMessage as an internal error — it formats
the rejection with {:?} into Status { code: 2, message: ... } and
replies with StatusCode::INTERNAL_SERVER_ERROR:
} else {
let reply = protobuf(Status {
code: 2,
message: format!("{err:?}"),
..Default::default()
});
Ok(warp::reply::with_status(
reply,
StatusCode::INTERNAL_SERVER_ERROR,
))
}
A client-side content-negotiation problem is therefore reported as a server
error with a Debug dump.
Suggested fix
Two independent improvements:
- Minimal: in the rejection path, distinguish client errors (unsupported
content type and similar filter rejections) from internal errors — return
415 Unsupported Media Type with a plain-text body such as
unsupported content type "application/json"; this endpoint requires application/x-protobuf.
- Full spec alignment: accept JSON on the OTLP/HTTP endpoints and
multiplex protobuf/JSON decoding based on the request Content-Type, as
the OTLP/HTTP spec recommends.
Configuration
sources:
otlp:
type: opentelemetry
http:
address: 0.0.0.0:4318
sinks:
console:
type: console
inputs: [otlp.logs]
encoding: { codec: json }
Version
0.58.0 (timberio/vector:0.58.0-debian); also reproduced on 0.55.0
Debug Output
Example Data
No response
Additional Context
No response
References
No response
A note for the community
Problem
Summary
The
opentelemetrysource's OTLP/HTTP endpoints only acceptContent-Type: application/x-protobuf. A request withContent-Type: application/json— an encoding the OTLP/HTTP spec defines andsays servers SHOULD accept — is rejected with 500 Internal Server Error
and a binary body: a protobuf-encoded
Statusmessage whose text is the RustDebugdump of the internal warp rejection:To a client this looks like a server crash, not an unsupported-media-type
condition.
Environment
timberio/vector:0.58.0-debian); also reproduced on 0.55.0opentelemetrysource, defaulthttpconfig (address: 0.0.0.0:4318)src/sources/opentelemetry/http.rsis unchanged onmaster as of that date
Steps to reproduce
Actual result
Body — 53 bytes of binary protobuf (hex):
Decoded: field 1 (varint) =
2(UNKNOWN), field 2 (string, 49 bytes) =Rejection(InvalidHeader { name: "content-type" })— the{:?}formattingof the warp rejection, serialized into a
Statusmessage.Control: the same request with
Content-Type: application/x-protobuf(evenan empty body) returns
200 OK; the official OpenTelemetry SDK protobufexporter works on the first attempt.
Expected result
At minimum
415 Unsupported Media Typewith a human-readable body naming theunsupported content type. Ideally, full JSON support — the OTLP/HTTP spec
says:
(The spec also requires the server to use the same
Content-Typein theresponse as it received in the request; the current response always
advertises
application/x-protobuf.)Root cause
src/sources/opentelemetry/http.rs:The route filter requires the header exactly, so any other content type
fails the filter and becomes a warp
Rejection(InvalidHeader):handle_rejection(the.recover()handler) treats every rejection thatis not the source's own
ErrorMessageas an internal error — it formatsthe rejection with
{:?}intoStatus { code: 2, message: ... }andreplies with
StatusCode::INTERNAL_SERVER_ERROR:A client-side content-negotiation problem is therefore reported as a server
error with a Debug dump.
Suggested fix
Two independent improvements:
content type and similar filter rejections) from internal errors — return
415 Unsupported Media Typewith a plain-text body such asunsupported content type "application/json"; this endpoint requires application/x-protobuf.multiplex protobuf/JSON decoding based on the request
Content-Type, asthe OTLP/HTTP spec recommends.
Configuration
Version
0.58.0 (
timberio/vector:0.58.0-debian); also reproduced on 0.55.0Debug Output
Example Data
No response
Additional Context
No response
References
No response