{"record":{"id":"897739dbc79a5585","repo":"karatelabs/karate","slug":"cannot-read-properties-of-object-reading-name","errorCode":null,"errorMessage":"cannot read properties of ${object} (reading '${name}')","messagePattern":"cannot read properties of (.+?) \\(reading '(.+?)'\\)","errorType":"exception","errorClass":"JsErrorException (typeError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java","lineNumber":936,"sourceCode":"                                     CoreContext context, boolean functionCall) {\n        return getByName(object, name, optional, context, functionCall, object);\n    }\n\n    /** Receiver-aware variant for super references (§13.3.7.3): the lookup\n     *  walks {@code object}'s chain, but any getter runs with {@code receiver}\n     *  as its {@code this}. All non-super callers pass {@code object} itself\n     *  via the delegating overload above. */\n    private static Object getByName(Object object, String name, boolean optional,\n                                     CoreContext context, boolean functionCall, Object receiver) {\n        if (object == null || object == Terms.UNDEFINED) {\n            // Reading a property of null/undefined is a TypeError (or undefined under ?.).\n            // Do NOT fall back to a same-named scope variable: `a.b.c` where `a.b` is null\n            // must not silently resolve to a variable `c` that happens to be in scope. That\n            // false resolution made `match obj.nullNode.id == '...'` pass by reading an\n            // unrelated `id` binding (e.g. a Scenario-Outline Examples column) instead of\n            // degrading to #notpresent.\n            if (optional) return Terms.UNDEFINED;\n            throw JsErrorException.typeError(\"cannot read properties of \" + object + \" (reading '\" + name + \"')\");\n        }\n\n        if (object instanceof JsObject jsObj) {\n            // Single own-slot probe replaces the historical containsKey +\n            // getMember pair (containsKey was exactly getOwnSlot != null, and\n            // the own-hit branch of 3-arg getMember is exactly slot.read).\n            PropertySlot own = jsObj.getOwnSlot(name);\n            if (own != null) {\n                return own.read(receiver, context);\n            }\n            Object result = jsObj.getMember(name, receiver, context);\n            if (isFound(result)) return result;\n            // JsValue wrappers may carry an original Java value (e.g. JsDate\n            // from a ZonedDateTime); route the missed lookup through it via\n            // the unified bridge fallback below so native methods like\n            // ZonedDateTime.format remain callable. A plain JsObject without\n            // an original returns UNDEFINED here — bridge access on a JS-only\n            // object would expose wrapper internals and shadow the","sourceCodeStart":918,"sourceCodeEnd":954,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java#L918-L954","documentation":"A TypeError from Karate's name-based property read: the base object was null or undefined when evaluating `base.name`. Karate deliberately does not fall back to a same-named scope variable (a past bug let `a.b.c` resolve `c` from scope when `a.b` was null), so this now fails loudly. Optional access (`?.`) or `optional` mode returns undefined instead.","triggerScenarios":"`a.b` where `a` is null/undefined, `match obj.nullNode.id == '...'` when `nullNode` is absent, chained path access in `match`/`assert`/`eval` on a missing response field, JS `karate.get` of a dotted path whose prefix doesn't exist.","commonSituations":"Reading nested fields from API responses where an intermediate node is missing, Scenario-Outline data where a column is present in some rows' payloads but not others, calling a helper that expects a populated object but receives null.","solutions":["Use optional chaining `obj.nullNode?.id` so a missing node degrades to undefined and matches `#notpresent`.","Guard the parent: `* def id = obj.nullNode ? obj.nullNode.id : null` or match the parent with `#present` first.","Fix the upstream data so the intermediate field exists.","Restructure the match to use Karate fuzzy markers (`##string`, `#notpresent`) instead of direct chained access."],"exampleFix":"// before\n* match obj.nullNode.id == '#notpresent'   // throws when nullNode is missing\n// after\n* match obj.nullNode?.id == '#notpresent'","handlingStrategy":"type-guard","validationCode":"* def id = obj?.nullNode?.id   // undefined instead of throw\n* match id == '#notpresent'","typeGuard":"function hasPath(obj, path) { return path.split('.').every(function (k) { return obj != null ? (obj = obj[k], true) : false; }); }","tryCatchPattern":null,"preventionTips":["Use ?. for every chained read over optional response fields.","Match intermediate nodes with #present before drilling in.","Don't rely on scope-variable fallbacks for missing nested fields.","Centralize payload extraction in helper features with guards."],"tags":["javascript","type-error","null-pointer","property-access"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}