nestjs/nest · error · InvalidGrpcPackageDefinitionMutexException

Invalid gRPC configuration. Both protoPath and packageDefini

Error message

Invalid gRPC configuration. Both protoPath and packageDefinition cannot be defined at the same time.

What it means

Thrown as InvalidGrpcPackageDefinitionMutexException from getGrpcPackageDefinition() when the gRPC options object defines BOTH options.protoPath AND options.packageDefinition. These are mutually exclusive ways to produce the package definition: protoPath tells @grpc/proto-loader to load+compile a .proto file at runtime, while packageDefinition is an already-built @grpc/proto-loader PackageDefinition. Specifying both is ambiguous, so the helper rejects it rather than silently picking one.

Source

Thrown at packages/microservices/helpers/grpc-helpers.ts:13

import { InvalidGrpcPackageDefinitionMissingPackageDefinitionException } from '../errors/invalid-grpc-package-definition-missing-package-definition.exception';
import { InvalidGrpcPackageDefinitionMutexException } from '../errors/invalid-grpc-package-definition-mutex.exception';
import { GrpcOptions } from '../interfaces';

export function getGrpcPackageDefinition(
  options: GrpcOptions['options'],
  grpcProtoLoaderPackage: any,
) {
  const file = options['protoPath'];
  const packageDefinition = options['packageDefinition'];

  if (file && packageDefinition) {
    throw new InvalidGrpcPackageDefinitionMutexException();
  }
  if (!file && !packageDefinition) {
    throw new InvalidGrpcPackageDefinitionMissingPackageDefinitionException();
  }

  return (
    packageDefinition ||
    grpcProtoLoaderPackage.loadSync(file, options['loader'])
  );
}

View on GitHub (pinned to 6ec0e2783d)

Solutions

  1. Provide exactly one source: either options.protoPath (plus optional loader/package), or options.packageDefinition (a proto-loader PackageDefinition object).
  2. If you precompiled the proto, delete protoPath from the gRPC options and pass only packageDefinition.
  3. Keep package and (when using packageDefinition) the loader options consistent so service lookup still works.

Example fix

// before
ClientProxyFactory.create({
  transport: Transport.GRPC,
  options: {
    protoPath: join(__dirname, 'user.proto'),
    packageDefinition: packageDef, // both set -> throws
    package: 'user',
  },
});

// after
ClientProxyFactory.create({
  transport: Transport.GRPC,
  options: {
    packageDefinition: packageDef,
    package: 'user',
  },
});
Defensive patterns

Strategy: validation

Validate before calling

function validateGrpcOptions(opts: any) {
  if (opts.protoPath && opts.packageDefinition) {
    throw new Error('Provide protoPath OR packageDefinition, not both.');
  }
  return opts;
}
validateGrpcOptions(grpcOptions);

Type guard

const hasBothProtoSources = (o: any): boolean => !!(o?.protoPath && o?.packageDefinition);

Try / catch

// Startup-time validation is the right pattern; remove one of the two options before construction.

Prevention

When it happens

Trigger: Calling ClientsModule.registerAsync or ClientProxyFactory.create for Transport.GRPC with options containing both { protoPath: './x.proto', packageDefinition: fromLoader }. Mixing a static packageDefinition import with a protoPath string in the same options object.

Common situations: Migrating from protoPath to a precompiled packageDefinition (e.g. grpc-tools output) and forgetting to remove protoPath. Copy-pasting options from an example that used protoPath and adding packageDefinition on top. Bundler config that injects protoPath defaults while the app also supplies packageDefinition.

Related errors


AI-assisted analysis of nestjs/nest@6ec0e2783d (2026-08-03). Data as JSON: /data/errors/d1f16cea680db609.json. Report an issue: GitHub.