ToolJet/ToolJet · error · GrpcOperationError

Service ${serviceName} not found in proto file

Error message

Service ${serviceName} not found in proto file

What it means

Thrown in buildProtoFileClient after loadProtoFromRemoteUrl + loadPackageDefinition succeed but findServiceInPackage(grpcObject, serviceName) returns null. The proto file downloaded and parsed, but the requested service name is not present in the loaded package definition. This is a name mismatch against the actual contents of the remote .proto.

Source

Thrown at plugins/packages/grpcv2/lib/operations.ts:113

    const cleanUrl = sanitizeGrpcServerUrl(sourceOptions.url, sourceOptions.ssl_enabled);
    const ServiceConstructor = service as new (url: string, credentials: any) => GrpcClient;
    const grpcClient = new ServiceConstructor(cleanUrl, credentials);

    return grpcClient;
  } catch (error: unknown) {
    const err = toError(error);
    throw new GrpcOperationError(`Failed to create reflection client for service ${serviceName}: ${err.message}`, error);
  }
};

export const buildProtoFileClient = async (sourceOptions: SourceOptions, serviceName: string): Promise<GrpcClient> => {
  try {
    const packageDefinition = await loadProtoFromRemoteUrl(sourceOptions.proto_file_url!);
    const grpcObject = grpc.loadPackageDefinition(packageDefinition);

    const service = findServiceInPackage(grpcObject, serviceName);
    if (!service) {
      throw new GrpcOperationError(`Service ${serviceName} not found in proto file`);
    }

    const credentials = buildChannelCredentials(sourceOptions);
    const cleanUrl = sanitizeGrpcServerUrl(sourceOptions.url, sourceOptions.ssl_enabled);

    if (typeof service !== 'function') {
      throw new GrpcOperationError(`Service ${serviceName} is not a valid constructor function`);
    }
    // Type assertion necessary for constructor function interface
    const ServiceConstructor = service as new (url: string, credentials: any) => GrpcClient;
    const client = new ServiceConstructor(cleanUrl, credentials);
    return client;
  } catch (error: unknown) {
    if (error instanceof GrpcOperationError) {
      throw error;
    }
    const err = toError(error);
    throw new GrpcOperationError(`Failed to create proto file client for service ${serviceName}: ${err.message}`, error);

View on GitHub (pinned to 20602a8e10)

Solutions

  1. Inspect the .proto at proto_file_url and confirm the exact service name and package it declares.
  2. Use the fully-qualified service name (package.service).
  3. Point proto_file_url to the correct proto file that actually defines the service.

Example fix

// before
sourceOptions.proto_file_url = 'https://host/user-v1.proto';
serviceName = 'UserService';
// after (proto declares package acme; service UserService)
serviceName = 'acme.UserService';
Defensive patterns

Strategy: validation

Validate before calling

async function verifyServiceInProtoUrl(url: string, serviceName: string) {
  const protoLoader = require('@grpc/proto-loader');
  const grpc = require('@grpc/grpc-js');
  const def = await protoLoader.load(url);
  const obj = grpc.loadPackageDefinition(def);
  const walk = (o: any, prefix = ''): string[] => {
    const out: string[] = [];
    for (const [k, v] of Object.entries(o)) {
      if (typeof v === 'function') out.push(prefix + k);
      else if (v && typeof v === 'object') out.push(...walk(v, prefix + k + '.'));
    }
    return out;
  };
  const names = walk(obj);
  if (!names.includes(serviceName)) throw new Error(`${serviceName} not in ${url}. Found: ${names.join(', ')}`);
}

Prevention

When it happens

Trigger: sourceOptions.proto_file_url points to a valid proto that does not declare serviceName; a short name used where the proto uses a fully-qualified name; wrong proto file URL for the intended service; proto uses a different package than expected.

Common situations: URL points to a proto for a different microservice; service renamed in the proto; package prefix not included in the lookup; multiple proto files and the wrong one was configured.

Related errors


AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13). Data as JSON: /api/errors/d5ed001bebbc60eb. Report an issue: GitHub.