karatelabs/karate · error · JsErrorException (typeError)
cannot read properties of
Error message
cannot read properties of ${object} (reading '[${i}]') What it means
A TypeError from Karate's indexed property access: the engine evaluated `expr[i]` where the base expression was null or undefined, so element i cannot be read. The engine first tries to parse the index as a dense integer; only when it is a valid non-negative index and the object is null/undefined does it throw. Optional chaining (`?.[`) bypasses this and returns undefined instead.
Solutions
- Guard the base value before indexing: check it is non-null (or use `karate.sizeOf()`/`karate.match`) or restructure the match to use `#present`/`#notpresent` markers.
- Use optional access `a.b?[0]` / `?.` syntax so a null base degrades to undefined instead of throwing.
- Fix the upstream data: ensure the API/call actually returns the expected array before indexing it.
- Provide a default: `* def items = response.items || []` before indexing.
Example fix
// before * match response.items[0].name == 'x' // after * def items = response.items || [] * match items[0].name == 'x'
Defensive patterns
Strategy: type-guard
Validate before calling
* def safe = response.items ? response.items : [] * assert karate.sizeOf(safe) > 0
Type guard
function isArrayLike(v) { return v != null && (Array.isArray(v) || karate.sizeOf(v) > 0); } Prevention
- Default missing arrays to [] before indexing.
- Match payloads against a schema (#array / ##[] ) before element access.
- Prefer fuzzy matchers (#present, #notpresent) over raw element reads for optional fields.
- Use optional chaining a?.b[0] for potentially null bases.
When it happens
Trigger: `null[0]`, `undefined[0]`, or chained access like `a.b[0]` where `a.b` is null/undefined; e.g. `match response.items[0] == ...` when the response has no `items`. Not thrown for Map/List bases (out-of-range List index just returns undefined).
Common situations: Reading array elements from an API response where an expected field is missing or null, empty-body responses, karate config JSON where a nested node is absent, match expressions written for a happy-path payload hitting an error payload.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- get by index [ ] for non-array
- cannot read properties of
- toBytes() argument must be a list of numbers, got
- toBytes() list must contain only numbers, got
- xmlPath() first argument must be XML node or string, but was
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/d2eaed45008c28bb.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:884
context.callReceiver = object;
return result;
}
private static Object getByIndex(Object object, Object index, boolean optional,
CoreContext context, boolean functionCall) {
JsSymbol sym = JsSymbol.keyedBy(index);
if (sym != null) {
// a minted symbol addresses the symbol store, never a string key
return object instanceof JsObject jo ? jo.getSymbolMember(sym, object, context) : Terms.UNDEFINED;
}
if (!functionCall && index instanceof Number n) {
int i = denseIndex(n);
if (i < 0) {
return getByName(object, Terms.toPropertyKey(index), optional, context, functionCall);
}
if (object == null || object == Terms.UNDEFINED) {
if (optional) return Terms.UNDEFINED;
throw JsErrorException.typeError("cannot read properties of " + object + " (reading '[" + i + "]')");
}
if (object instanceof JsArray array) {
return array.getIndexedValue(i, array, context);
}
if (object instanceof List<?> list) {
if (i < 0 || i >= list.size()) return Terms.UNDEFINED;
// Translate JsArray.HOLE → undefined so callers reading from
// a raw List that was sourced from a sparse JsArray (e.g.
// Array.prototype.* methods that return rawList directly)
// never see the sentinel.
return JsArray.unwrapHole(list.get(i));
}
if (object instanceof String s) {
if (i < 0 || i >= s.length()) return Terms.UNDEFINED;
return s.substring(i, i + 1);
}
if (object instanceof byte[] bytes) {
if (i < 0 || i >= bytes.length) return Terms.UNDEFINED;View on GitHub (pinned to a22eb90246)