{"record":{"id":"835cdf11780d4253","repo":"louislam/uptime-kuma","slug":"empty-or-undefined-response-check-query-syntax-an","errorCode":null,"errorMessage":"Empty or undefined response. Check query syntax and response structure","messagePattern":"Empty or undefined response\\. Check query syntax and response structure","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/util.ts","lineNumber":710,"sourceCode":"    jsonPath: string,\n    jsonPathOperator: string,\n    expectedValue: any\n): Promise<{ status: boolean; response: any }> {\n    // Attempt to parse data as JSON; if unsuccessful, handle based on data type.\n    let response: any;\n    try {\n        response = JSON.parse(data);\n    } catch {\n        response =\n            (typeof data === \"object\" || typeof data === \"number\") && !Buffer.isBuffer(data) ? data : data.toString();\n    }\n\n    try {\n        // If a JSON path is provided, pre-evaluate the data using it.\n        response = jsonPath ? await jsonata(jsonPath).evaluate(response) : response;\n\n        if (response === null || response === undefined) {\n            throw new Error(\"Empty or undefined response. Check query syntax and response structure\");\n        }\n\n        // Check for arrays: JSONata filter expressions like .[predicate] always return arrays\n        if (Array.isArray(response)) {\n            const responseStr = JSON.stringify(response);\n            const truncatedResponse = responseStr.length > 25 ? responseStr.substring(0, 25) + \"...]\" : responseStr;\n            throw new Error(\n                \"JSON query returned the array \" +\n                    truncatedResponse +\n                    \", but a primitive value is required. \" +\n                    \"Modify your query to return a single value via [0] to get the first element or use an aggregation like $count(), $sum() or $boolean().\"\n            );\n        }\n\n        if (typeof response === \"object\" || response instanceof Date || typeof response === \"function\") {\n            throw new Error(\n                `The post-JSON query evaluated response from the server is of type ${typeof response}, which cannot be directly compared to the expected value`\n            );","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/src/util.ts#L692-L728","documentation":"Thrown by evaluateJsonQuery() in src/util.ts when, after applying the JSONata jsonPath to the parsed response, the result is `null` or `undefined`. This is the json-query monitor's strict guard: the configured JSON path must resolve to an actual value before comparison. It exists so a missing field is treated as a monitor failure rather than a silent false-negative.","triggerScenarios":"A json-query monitor whose jsonPath selects a field absent from the response (e.g. `$.status` when the body has no such key), a path whose predicate matches nothing (e.g. `$.items[id='999']` returning undefined), a JSONata expression that evaluates to null, or an empty response body where jsonPath still runs. Called from monitor.js:712, snmp.js:63, globalping.js:417.","commonSituations":"Target API changed its schema and dropped/renamed the field; endpoint returns an error body without the expected field; JSONata path was written against documentation that is out of date; the response is HTML/error page that parsed to a non-object; conditional field that is only present on success.","solutions":["Test the jsonPath against a sample response body with a JSONata playground or `jsonata(path).evaluate(sample)`.","Make the path resilient: use a fallback or pick a field that is always present, or `$lookup` with a default.","Verify the endpoint actually returns the field for the request the monitor sends (auth, params).","If absence should mean DOWN, catch this error and map it to a DOWN status instead of a thrown exception."],"exampleFix":"// before: monitor.jsonPath = \"$.status\"  but body is { \"state\": \"ok\" } -> undefined -> throws\n\n// after: monitor.jsonPath = \"$.state\"\n// or make absence explicit in the path (JSONata):\n//   monitor.jsonPath = \"($ := $.status; $ ? $ : 'unknown')\"","handlingStrategy":"validation","validationCode":"const probe = await jsonata(jsonPath).evaluate(sample);\nif (probe === null || probe === undefined) throw new Error(\"Path resolves to nothing on sample\");","typeGuard":"const resolvesToValue = (v) => v !== null && v !== undefined;","tryCatchPattern":"try { await evaluateJsonQuery(data, jsonPath, op, expected); } catch (e) { if (/Empty or undefined/.test(e.message)) status = DOWN; else throw e; }","preventionTips":["Test the JSONata path against a real sample response.","Choose a field that is always present on success.","Treat absence as DOWN explicitly rather than letting the error surface."],"tags":["json-query","jsonata","monitor","validation","typescript","uptime-kuma"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}