vectordotdev/vector · error
Failed to build reflection service
Error message
Failed to build reflection service
What it means
When the Vector gRPC API server starts, it configures a tonic gRPC server reflection service from the embedded observability and health file descriptor sets and panics if `Builder::build()` fails. Reflection fails to build only when the encoded descriptor sets are invalid or empty, so this panic points to a build/codegen problem with the embedded protobuf descriptors, not runtime conditions.
Solutions
- Rebuild from clean (`cargo clean`) so `protoc`/tonic codegen regenerates the FILE_DESCRIPTOR_SET constants
- Verify tonic, tonic-reflection, and tonic-health versions are mutually compatible in Cargo.lock
- Confirm the build script that emits FILE_DESCRIPTOR_SET runs and the file descriptor set is non-empty
- Pin known-good tonic/tonic-reflection versions if a recent dependency bump introduced the failure
Example fix
// before (incompatible tonic-reflection after cargo update)
.build().expect("Failed to build reflection service");
// after
$ cargo update -p tonic-reflection --precise 0.x.y # match workspace tonic
$ cargo clean && cargo build Defensive patterns
Strategy: retry
Validate before calling
assert!(!crate::proto::observability::FILE_DESCRIPTOR_SET.is_empty()); assert!(!tonic_health::pb::FILE_DESCRIPTOR_SET.is_empty());
Try / catch
let reflection = tonic_reflection::server::Builder::configure()
.register_encoded_file_descriptor_set(crate::proto::observability::FILE_DESCRIPTOR_SET)
.build()
.map_err(|e| { error!("reflection service build failed: {e}"); e })?; Prevention
- Pin compatible tonic/tonic-reflection/tonic-health versions in Cargo.toml
- cargo clean after upgrading tonic-family dependencies so descriptor sets regenerate
- Verify generated FILE_DESCRIPTOR_SET bytes in a build/test assertion
When it happens
Trigger: Calling `start` for the gRPC API when `tonic_reflection::server::Builder::configure().build()` returns Err — corrupted or empty `FILE_DESCRIPTOR_SET` constants (bad tonic/protoc codegen output).
Common situations: Mismatched tonic/tonic-reflection/protoc versions generating empty or malformed descriptor sets; regenerating protos with a broken build script; unusual feature-flag combinations excluding the descriptor.
Related errors
- Failed to build HTTP server from TCP listener
- Failed to set up SIGINT handler.
- metrics initialization failed
- Unable to create async runtime
- a record with a next ID must have an event count
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/637a804087fbe825.
Report an issue: GitHub.
Appendix: source
Thrown at src/api/grpc_server.rs:91
let std_listener = listener
.into_std()
.map_err(|e| crate::Error::from(format!("Failed to convert TCP listener: {e}")))?;
std_listener.set_nonblocking(true).map_err(|e| {
crate::Error::from(format!("Failed to set TCP listener non-blocking: {e}"))
})?;
let router_serving = Arc::clone(&serving);
// Spawn the server with the already-bound listener
crate::spawn_in_current_span(async move {
// Build reflection service for tools like grpcurl
let reflection_service = tonic_reflection::server::Builder::configure()
.register_encoded_file_descriptor_set(
crate::proto::observability::FILE_DESCRIPTOR_SET,
)
.register_encoded_file_descriptor_set(tonic_health::pb::FILE_DESCRIPTOR_SET)
.build()
.expect("Failed to build reflection service");
// Build the tonic router (gRPC services) and merge with the HTTP router
// so both protocols share the same port. `accept_http1(true)` lets plain
// HTTP/1.1 requests reach the merged axum routes.
let router = TonicServer::builder()
.accept_http1(true)
.add_service(health_service)
.add_service(ObservabilityServer::new(service))
.add_service(reflection_service)
.into_router()
.merge(http_router(router_serving));
let result = hyper::Server::from_tcp(std_listener)
.expect("Failed to build HTTP server from TCP listener")
.serve(router.into_make_service())
.with_graceful_shutdown(async {
rx.await.ok();
info!("GRPC API server shutting down.");View on GitHub (pinned to bdb87aeaa4)