{"record":{"id":"637a804087fbe825","repo":"vectordotdev/vector","slug":"failed-to-build-reflection-service","errorCode":null,"errorMessage":"Failed to build reflection service","messagePattern":"Failed to build reflection service","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/api/grpc_server.rs","lineNumber":91,"sourceCode":"        let std_listener = listener\n            .into_std()\n            .map_err(|e| crate::Error::from(format!(\"Failed to convert TCP listener: {e}\")))?;\n        std_listener.set_nonblocking(true).map_err(|e| {\n            crate::Error::from(format!(\"Failed to set TCP listener non-blocking: {e}\"))\n        })?;\n\n        let router_serving = Arc::clone(&serving);\n\n        // Spawn the server with the already-bound listener\n        crate::spawn_in_current_span(async move {\n            // Build reflection service for tools like grpcurl\n            let reflection_service = tonic_reflection::server::Builder::configure()\n                .register_encoded_file_descriptor_set(\n                    crate::proto::observability::FILE_DESCRIPTOR_SET,\n                )\n                .register_encoded_file_descriptor_set(tonic_health::pb::FILE_DESCRIPTOR_SET)\n                .build()\n                .expect(\"Failed to build reflection service\");\n\n            // Build the tonic router (gRPC services) and merge with the HTTP router\n            // so both protocols share the same port. `accept_http1(true)` lets plain\n            // HTTP/1.1 requests reach the merged axum routes.\n            let router = TonicServer::builder()\n                .accept_http1(true)\n                .add_service(health_service)\n                .add_service(ObservabilityServer::new(service))\n                .add_service(reflection_service)\n                .into_router()\n                .merge(http_router(router_serving));\n\n            let result = hyper::Server::from_tcp(std_listener)\n                .expect(\"Failed to build HTTP server from TCP listener\")\n                .serve(router.into_make_service())\n                .with_graceful_shutdown(async {\n                    rx.await.ok();\n                    info!(\"GRPC API server shutting down.\");","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/src/api/grpc_server.rs#L73-L109","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before (incompatible tonic-reflection after cargo update)\n.build().expect(\"Failed to build reflection service\");\n// after\n$ cargo update -p tonic-reflection --precise 0.x.y  # match workspace tonic\n$ cargo clean && cargo build","handlingStrategy":"retry","validationCode":"assert!(!crate::proto::observability::FILE_DESCRIPTOR_SET.is_empty());\nassert!(!tonic_health::pb::FILE_DESCRIPTOR_SET.is_empty());","typeGuard":null,"tryCatchPattern":"let reflection = tonic_reflection::server::Builder::configure()\n    .register_encoded_file_descriptor_set(crate::proto::observability::FILE_DESCRIPTOR_SET)\n    .build()\n    .map_err(|e| { error!(\"reflection service build failed: {e}\"); e })?;","preventionTips":["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"],"tags":["grpc","tonic","rust","reflection","startup"],"backgroundTag":"module-init-failed","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}