louislam/uptime-kuma · warning · Error

Query evaluation returned undefined. Check query syntax and

Error message

Query evaluation returned undefined. Check query syntax and the structure of the response data

What it means

Thrown by evaluateJsonQuery() after evaluating the compiled JSONata comparison expression when `status === undefined`. Unlike null/false, undefined means JSONata could not produce a result at all — typically a type error such as `$number(...)` on a non-numeric value, or `$contains` on a non-string. The function treats this distinctly from a legitimate false result.

Source

Thrown at src/util.ts:761

            case "==":
                jsonQueryExpression = "$.value = $.expected";
                break;
            case "contains":
                jsonQueryExpression = "$contains($.value, $.expected)";
                break;
            default:
                throw new Error(`Invalid condition ${jsonPathOperator}`);
        }

        // Evaluate the JSON Query Expression
        const expression = jsonata(jsonQueryExpression);
        const status = await expression.evaluate({
            value: response.toString(),
            expected: expectedValue.toString(),
        });

        if (status === undefined) {
            throw new Error(
                "Query evaluation returned undefined. Check query syntax and the structure of the response data"
            );
        }

        return {
            status, // The evaluation of the json query
            response, // The response from the server or result from initial json-query evaluation
        };
    } catch (err: any) {
        response = JSON.stringify(response); // Ensure the response is treated as a string for the console
        response = response && response.length > 50 ? `${response.substring(0, 100)}… (truncated)` : response; // Truncate long responses to the console
        throw new Error(`Error evaluating JSON query: ${err.message}. Response from server was: ${response}`);
    }
}

// these types will have domain expiry support via the specified field
export const TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD = {
    http: "url",

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Match the operator to the value type: numeric operators require numeric values, `contains` requires strings.
  2. Provide a concrete expectedValue of the right type for the chosen operator.
  3. Coerce the value inside the path: `monitor.jsonPath = "$number($.field)"` for numeric comparison.
  4. If the value may be missing, default it in JSONata: `($ := $.field; $count($match($, /\d+/)) > 0 ? $number($) : 0)`.

Example fix

// before: value is "12.5%" (string), operator ">", expected "90"
//   $number("12.5%") -> undefined -> status undefined -> throws

// after: strip the unit in the path, then compare
//   monitor.jsonPath = "$number($replace($.field, '%', ''))"
//   operator ">", expectedValue "90"
Defensive patterns

Strategy: validation

Validate before calling

const probe = await jsonata(`$number(${jsonPath})`).evaluate(sample);
if (probe === undefined && [">", ">=", "<", "<="].includes(operator)) throw new Error("Value not numeric");

Type guard

const isNumericCompareSafe = (v, op) => ![">", ">=", "<", "<="].includes(op) || (typeof v === "number" && !Number.isNaN(v));

Try / catch

try { await evaluateJsonQuery(data, path, op, expected); } catch (e) { if (/returned undefined/.test(e.message)) { path = "$number(" + path + ")"; /* retry */ } else throw e; }

Prevention

When it happens

Trigger: Using a comparison operator (>, >=, <, <=) where the selected value is non-numeric, so `$number($.value)` returns undefined; using `contains` where either value or expected is not a string; JSONata silently returning undefined due to type coercion failure inside the generated expression `$number($.value) <op> $number($.expected)`.

Common situations: expectedValue left blank for a numeric operator; the field is a string where a number was expected; locale-formatted numbers ("1.234,56") that `$number` rejects; null/empty value reaching the comparator after passing earlier null checks (it can't — null is caught earlier — but a JSONata intermediate can still be undefined).

Related errors


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