{"record":{"id":"71ad1b93d745f791","repo":"karatelabs/karate","slug":"expression-expr-cause-message","errorCode":null,"errorMessage":"expression: <expr> - <cause message>","messagePattern":"expression: <expr> - <cause message>","errorType":"exception","errorClass":"java.lang.RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java","lineNumber":735,"sourceCode":"                object = Interpreter.eval(node.getFirst(), context);\n            } catch (Exception e) {\n                if (context.root.bridge != null) {\n                    String base = node.getFirst().getText();\n                    String path = base + \".\" + name;\n                    ExternalAccess ja = context.root.bridge.forType(path);\n                    if (ja != null) {\n                        if (wantReceiver) context.callReceiver = null;\n                        if (functionCall) {\n                            return (JsConstructor) (c, args) -> ja.construct(args);\n                        }\n                        return ja;\n                    }\n                    object = context.root.bridge.forType(base);\n                } else {\n                    object = null;\n                }\n                if (object == null) {\n                    throw new RuntimeException(\"expression: \" + node.getFirst().getText() + \" - \" + e.getMessage(), e);\n                }\n            }\n            // Propagate short-circuit from a deeper ?. step.\n            if (object == SHORT_CIRCUITED) return SHORT_CIRCUITED;\n            // Local ?. fires here.\n            if (optional && (object == null || object == Terms.UNDEFINED)) return SHORT_CIRCUITED;\n        } else {\n            optional = true;\n            if (node.get(1).type == NodeType.REF_BRACKET_EXPR) {\n                object = Interpreter.eval(node.getFirst(), context);\n                if (object == SHORT_CIRCUITED) return SHORT_CIRCUITED;\n                // ?.[expr] fires here — index is not evaluated when short-circuiting.\n                if (object == null || object == Terms.UNDEFINED) return SHORT_CIRCUITED;\n                Object index = Interpreter.eval(node.get(1).get(2), context);\n                Object v = getByIndex(object, index, false, context, functionCall);\n                if (wantReceiver) context.callReceiver = object;\n                return v;\n            } else {","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java#L717-L753","documentation":"When evaluating a property/index access chain, PropertyAccess catches an underlying evaluation failure and, if it cannot resolve a bridge/type for the base object, rethrows as \"expression: <expr> - <cause message>\". It wraps the original cause, so the real failure (unknown variable, bad method, null base) is in the chained exception.","triggerScenarios":"A dot/bracket access chain where an intermediate evaluation throws and the base object cannot be determined — e.g. referencing an undefined variable then calling a member (x.foo() with x undefined), or an expression on a null/unknown context value.","commonSituations":"Typos in Karate script variables, accessing members of a response field that does not exist, calling Java interop methods on undefined values, schema/config keys not set before the expression runs.","solutions":["Read the chained cause message to find the real failure (undefined variable, missing method, etc.).","Assert/validate the variable exists before the expression: use karate.match or a JS typeof/null check.","Fix the typo or ensure the upstream step that produces the base object actually ran and set the value."],"exampleFix":"// before (Karate script)\n* def x = response.data.items[0].name // expression: response.data.items[0].name - ... if data missing\n// after\n* assert response.data != null\n* def items = response.data.items || []\n* def x = items.length ? items[0].name : null","handlingStrategy":"validation","validationCode":"// Karate script: validate base values before member access\n* assert response != null && response.data != null\n* def items = response.data ? (response.data.items || []) : []","typeGuard":"// JS in Karate\nfunction safeGet(obj, path) {\n  return path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj);\n}","tryCatchPattern":"try {\n    value = karate.eval(expression);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"expression:\")) {\n        logger.warn(\"failed expression: {} cause: {}\", expression, e.getCause());\n        value = null; // or default\n    } else throw e;\n}","preventionTips":["Always verify variables/fields exist before chaining member access.","Use optional chaining (?.) in JS expressions to short-circuit null/undefined.","Check the wrapped cause (getCause()) — it names the real failure.","Assert upstream API responses with karate.match before using nested fields."],"tags":["javascript","expression-evaluation","property-access","wrapped-exception"],"backgroundTag":"unexpected-response-shape","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}