#3970·Checkmate

gRPC monitors fail with ENOENT: health.proto path does not resolve

Author: web-engineerCreated Sep 17, 2026Updated Sep 18, 2026

Describe the bug

gRPC monitors never run. GrpcProvider resolves the health proto relative to its own file:

typescript
// server/src/service/network/GrpcProvider.ts:67
const protoPath = path.join(path.dirname(currentFilePath), "protos", "health.proto");

GrpcProvider.ts is in src/service/network/, so that resolves to src/service/network/protos/health.proto. The file is at src/service/protos/health.proto. Every gRPC check throws before it reaches the network:

[JobQueue](runJob:check) ENOENT: no such file or directory,
  open '/app/src/service/network/protos/health.proto'

The job fails rather than recording a check, so the monitor sits at initializing indefinitely and failCount climbs with nothing in the checks table to explain it.

The published image has the same fault plus a second one. npm run build copies only src/templates, so no .proto reaches dist at all:

bash
$ docker run --rm --entrypoint sh ghcr.io/bluewave-labs/checkmate:develop \
    -c 'find /app/server/dist -name "*.proto"'
(no output)

$ docker run --rm --entrypoint sh ghcr.io/bluewave-labs/checkmate:develop \
    -c 'grep -n "health.proto" /app/server/dist/service/network/GrpcProvider.js'
52:  const protoPath = path.join(path.dirname(currentFilePath), "protos", "health.proto");

The only copy in the image is the untouched src tree, which dist/index.js does not read.

To Reproduce

  1. Create a monitor of type grpc against any host and port.
  2. Watch the server log: ENOENT … src/service/network/protos/health.proto.
  3. The monitor stays initializing; db.jobs.findOne({_id: "check:<monitorId>"}) shows runCount: 0 and a rising failCount with that lastFailReason.

Expected behavior

The proto loads and the health check runs.

Additional context

Present on develop at f4864b545 and in ghcr.io/bluewave-labs/checkmate:develop.

It has been this way since c7689cc64 (5 March 2026), which added GrpcProvider.ts under infrastructure/network/ while the proto stayed at infrastructure/protos/. d022f7d84 moved both and preserved the relative mistake. The unit tests inject a stubbed protoLoader, so they pass either way.

Two changes are needed, since fixing the path alone still leaves the image without the file:

  • point protoPath at the directory the proto is actually in, and
  • copy it into dist during the build, as src/templates already is.

Found while testing the egress self-check (#3937) against a live instance; unrelated to that work.