louislam/uptime-kuma · error · Error

keyword [ ] is in [" + + "]

Error message

keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${truncatedResponse} + "]

What it means

Thrown by the gRPC keyword monitor when the keyword presence in the response does not match isInvertKeyword(). NOTE: there is a formatting bug in the thrown message — the template literal mixes backtick interpolation with literal string-concatenation syntax, so the output reads `...in [" + <value> + "]` with literal quotes and plus signs rather than clean text. The underlying logic (keyword mismatch) is unaffected.

Solutions

  1. Confirm the keyword actually appears in the raw gRPC response string
  2. Verify isInvertKeyword: invert means UP when the keyword is ABSENT
  3. Serialize the real gRPC response once to confirm what string is being searched
  4. Optionally fix the cosmetic template-literal bug so the message is readable

Example fix

// before (line 33-35): broken template/concat mix
throw new Error(
    `keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${truncatedResponse} + "]`
);
// after: clean template literal
throw new Error(
    `keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [${truncatedResponse}]`
);
Defensive patterns

Strategy: validation

Validate before calling

// Validate gRPC keyword config before running
if (!monitor.keyword || monitor.keyword.length === 0) {
    throw new Error("gRPC keyword monitor has no keyword set");
}

Try / catch

// Preserve the keyword result classification for alerting
if (keywordFound !== !monitor.isInvertKeyword()) {
    throw new Error(`keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [${truncatedResponse}]`);
}

Prevention

When it happens

Trigger: keywordFound !== !monitor.isInvertKeyword(). If not inverted and keyword absent -> throw 'not present'; if inverted and keyword present -> throw 'present'. The response is stringified then truncated to 47 chars for the message.

Common situations: Wrong keyword for the gRPC response payload, the service moved to a different message shape, invert keyword toggled by mistake, or the response is an error message that does/doesn't contain the keyword.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/fd6c8f54dd5bea6a. Report an issue: GitHub.

Appendix: source

Thrown at server/monitor-types/grpc.js:33

        const service = this.constructGrpcService(
            monitor.grpcUrl,
            monitor.grpcProtobuf,
            monitor.grpcServiceName,
            monitor.grpcEnableTls
        );
        let response = await this.grpcQuery(service, monitor.grpcMethod, monitor.grpcBody);
        heartbeat.ping = dayjs().valueOf() - startTime;
        log.debug(this.name, "gRPC response:", response);
        let keywordFound = response.toString().includes(monitor.keyword);
        if (keywordFound !== !monitor.isInvertKeyword()) {
            log.debug(
                this.name,
                `GRPC response [${response}] + ", but keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${response} + "]"`
            );

            let truncatedResponse = response.length > 50 ? response.toString().substring(0, 47) + "..." : response;

            throw new Error(
                `keyword [${monitor.keyword}] is ${keywordFound ? "present" : "not"} in [" + ${truncatedResponse} + "]`
            );
        }
        heartbeat.status = UP;
        heartbeat.msg = `${response}, keyword [${monitor.keyword}] ${keywordFound ? "is" : "not"} found`;
    }

    /**
     * Create gRPC client
     * @param {string} url grpc Url
     * @param {string} protobufData grpc ProtobufData
     * @param {string} serviceName grpc ServiceName
     * @param {string} enableTls grpc EnableTls
     * @returns {grpc.Service} grpc Service
     */
    constructGrpcService(url, protobufData, serviceName, enableTls) {
        const protocObject = protojs.parse(protobufData);
        const protoServiceObject = protocObject.root.lookupService(serviceName);

View on GitHub (pinned to 6b5ea01557)