louislam/uptime-kuma · error · Error
keyword [${monitor.keyword}] is ${keywordFound ? "present" :
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.
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)
Solutions
- Confirm the keyword actually appears in the raw gRPC response string
- Verify isInvertKeyword: invert means UP when the keyword is ABSENT
- Serialize the real gRPC response once to confirm what string is being searched
- 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
- Confirm the keyword appears in the stringified gRPC response
- Remember isInvertKeyword semantics: invert = UP when keyword is absent
- Fix the cosmetic template-literal bug so alert messages are readable
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
- No record matched.
- ${heartbeat.msg}, but keyword is ${keywordFound ? "present"
- Invalid db-config.json, type must be a string
- Unknown Database type: ${dbConfig.type}
- ${bean.msg}, but keyword is ${present|not} in [${data}]
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/fd6c8f54dd5bea6a.
Report an issue: GitHub.