{"id":15334,"library":"grpc-server-reflection","title":"gRPC Server Reflection for Node.js","description":"grpc-server-reflection is a Node.js library that implements the gRPC server reflection protocol, allowing gRPC clients to discover services and methods exposed by a server at runtime without prior knowledge of its `.proto` definitions. Currently at version 0.1.5, it provides robust reflection capabilities by leveraging pre-generated binary descriptor sets (via `grpc_tools_node_protoc`) rather than relying on dynamic schema parsing or problematic `protobuf-js` binary formats. It is designed to be framework-agnostic and offers full support for both the modern `@grpc/grpc-js` library and the older `grpc` package. Key differentiators include its comprehensive service detection, full feature set compared to alternatives, and its ability to handle complex `proto` definitions via a static descriptor file. While the release cadence is not explicitly defined, given its pre-1.0 version, users can expect incremental updates for bug fixes and stability improvements.","status":"active","version":"0.1.5","language":"javascript","source_language":"en","source_url":"https://github.com/AckeeCZ/grpc-server-reflection","tags":["javascript","grpc","reflection","nodejs","server","descriptor set","proto","service","introspection"],"install":[{"cmd":"npm install grpc-server-reflection","lang":"bash","label":"npm"},{"cmd":"yarn add grpc-server-reflection","lang":"bash","label":"yarn"},{"cmd":"pnpm add grpc-server-reflection","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core gRPC library for Node.js servers that this package integrates with for reflection functionality.","package":"@grpc/grpc-js","optional":false},{"reason":"Supports the older gRPC Node.js library for server reflection as well.","package":"grpc","optional":true}],"imports":[{"note":"This package primarily targets ESM environments for modern Node.js development. For CommonJS, require syntax is generally `const { addReflection } = require('grpc-server-reflection');`","wrong":"const { addReflection } = require('grpc-server-reflection')","symbol":"addReflection","correct":"import { addReflection } from 'grpc-server-reflection'"},{"note":"While named imports for `Server` might work in some CJS transpiled environments, the standard CJS pattern for `@grpc/grpc-js` is to import the entire module and access `Server` as a property. For ESM, named imports are typically used for specific symbols like `ServerUnaryCall` but `Server` itself is often accessed via a wildcard import.","wrong":"const { Server } = require('@grpc/grpc-js');","symbol":"Server","correct":"import * as grpc from '@grpc/grpc-js'; const server = new grpc.Server()"},{"note":"TypeScript users will often import types like `ServerUnaryCall` directly for type safety in service implementations.","wrong":"const ServerUnaryCall = require('@grpc/grpc-js').ServerUnaryCall","symbol":"ServerUnaryCall","correct":"import { ServerUnaryCall } from '@grpc/grpc-js'"}],"quickstart":{"code":"import * as grpc from '@grpc/grpc-js';\nimport { addReflection } from 'grpc-server-reflection';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// --- Placeholder for your proto definition ---\n// syntax = \"proto3\";\n// package myapp;\n// service Greeter {\n//   rpc SayHello (HelloRequest) returns (HelloReply) {}\n// }\n// message HelloRequest { string name = 1; }\n// message HelloReply { string message = 1; }\n// ------------------------------------------\n\n// Dummy service implementation\nconst greeterService = {\n  SayHello: (call: grpc.ServerUnaryCall<any, any>, callback: grpc.sendUnaryData<any>) => {\n    const name = call.request.name || 'World';\n    callback(null, { message: `Hello, ${name}!` });\n  },\n};\n\n// Resolve paths for descriptor set\nconst DESCRIPTOR_SET_PATH = path.resolve(__dirname, 'descriptor_set.bin');\n\n// In a real application, you must generate descriptor_set.bin using grpc_tools_node_protoc:\n// grpc_tools_node_protoc --descriptor_set_out=${DESCRIPTOR_SET_PATH} --include_imports your_protos/**/*.proto\nif (!fs.existsSync(DESCRIPTOR_SET_PATH)) {\n  console.warn(`\n  WARNING: Descriptor set file not found at ${DESCRIPTOR_SET_PATH}.\n  Reflection will not function without it. Please generate it.\n  Example command:\n  grpc_tools_node_protoc --descriptor_set_out=${DESCRIPTOR_SET_PATH} --include_imports --proto_path=./path/to/protos ./path/to/protos/*.proto\n  `);\n  // For quickstart to be runnable without actual proto generation, create a dummy file.\n  // In production, this file *must* be correctly generated.\n  fs.writeFileSync(DESCRIPTOR_SET_PATH, Buffer.from('DUMMY_DESCRIPTOR_SET'));\n}\n\nconst server = new grpc.Server();\n\n// Register your actual gRPC services\nserver.addService({\n  // This is a minimal representation; real services use generated types.\n  SayHello: {\n    path: '/myapp.Greeter/SayHello',\n    requestStream: false,\n    responseStream: false,\n    requestSerialize: (value: any) => Buffer.from(JSON.stringify(value)),\n    requestDeserialize: (buffer: Buffer) => JSON.parse(buffer.toString()),\n    responseSerialize: (value: any) => Buffer.from(JSON.stringify(value)),\n    responseDeserialize: (buffer: Buffer) => JSON.parse(buffer.toString()),\n  },\n}, greeterService);\n\n// Add gRPC server reflection to the server instance\naddReflection(server, DESCRIPTOR_SET_PATH);\n\nconst port = '0.0.0.0:50051';\nserver.bindAsync(port, grpc.ServerCredentials.createInsecure(), (err, boundPort) => {\n  if (err) {\n    console.error(`Server bind failed on ${port}: ${err.message}`);\n  } else {\n    server.start();\n    console.log(`gRPC server listening on ${boundPort} with reflection enabled.`);\n  }\n});","lang":"typescript","description":"This quickstart demonstrates how to initialize a gRPC server with a placeholder service and then integrate `grpc-server-reflection` using a pre-generated descriptor set, enabling clients to introspect the server's capabilities."},"warnings":[{"fix":"Ensure your protocol buffer compilation command includes `--include_imports`, e.g., `grpc_tools_node_protoc --descriptor_set_out=path/to/descriptor_set.bin --include_imports ./api/**/*.proto`.","message":"The `grpc_tools_node_protoc` command used to generate the descriptor set *must* include the `--include_imports` flag. Omitting this flag will result in an incomplete descriptor set, causing clients to fail when trying to reflect imported types or services.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"This is generally not an issue as clients typically do not need to reflect on the reflection service. If a specific tool requires it, you would need to manually add the reflection service definition to your descriptor set compilation.","message":"The server reflection service itself (usually `grpc.reflection.v1alpha.ServerReflection`) is not automatically included in the descriptor set generated by `protoc` unless explicitly defined within one of your `.proto` files and included in the compilation. This means clients cannot reflect upon the reflection service itself.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Integrate `grpc_tools_node_protoc` into your build process to generate the `descriptor_set.bin` file before your application starts, ensuring it's accessible at the path provided to `addReflection`.","message":"This package relies on a pre-generated binary descriptor set file (e.g., `descriptor_set.bin`). It does not dynamically parse `.proto` files at runtime. Users must ensure this file is correctly generated and available to the server.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Pin exact versions (`0.x.y`) in `package.json` for production deployments and manually test upgrades before rolling out to avoid unexpected behavior.","message":"Being a pre-1.0.0 package (current version 0.1.5), its API might not be entirely stable, and future minor versions could introduce breaking changes or significant modifications. Exercise caution when upgrading and review release notes.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Verify that `path/to/descriptor_set.bin` is the correct and absolute path to your generated descriptor set file and that the Node.js process has read permissions for it. Ensure the file was generated by `grpc_tools_node_protoc`.","cause":"The binary descriptor set file specified in `addReflection` does not exist or is not accessible.","error":"Error: Failed to load descriptor set from path/to/descriptor_set.bin"},{"fix":"Re-run `grpc_tools_node_protoc` to generate your `descriptor_set.bin` file, explicitly adding the `--include_imports` flag, e.g., `grpc_tools_node_protoc --descriptor_set_out=output.bin --include_imports your_protos/**/*.proto`.","cause":"The descriptor set was generated without `--include_imports`, leading to an incomplete view of the service definitions, especially for services that import other proto files.","error":"gRPC reflection client fails to discover methods/services, or reports 'No such method' errors."},{"fix":"For ESM projects, use `import { addReflection } from 'grpc-server-reflection'`. For CommonJS, if the package explicitly supports it, use `const { addReflection } = require('grpc-server-reflection');`. Ensure your `package.json` `type` field is correctly set to `module` for ESM, or use a bundler that handles CJS/ESM interop.","cause":"This typically occurs when mixing CommonJS `require()` with an ESM-only package or when using incorrect destructuring with `require()`.","error":"TypeError: addReflection is not a function"}],"ecosystem":"npm"}