Skip to content

opentelemetry source: OTLP/HTTP+JSON requests get 500 with a protobuf Debug-dump body instead of 415 (protobuf-only) #26456

Description

@paveljanda

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:

  1. 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",
    ))
  2. 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:

  1. 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.
  2. 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

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions