{"record":{"id":"f128e95fc3d9e876","repo":"karatelabs/karate","slug":"get-by-index-i-for-non-array-object","errorCode":null,"errorMessage":"get by index [${i}] for non-array: ${object}","messagePattern":"get by index \\[(.+?)\\] for non-array: (.+?)","errorType":"exception","errorClass":"JsErrorException (typeError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java","lineNumber":912,"sourceCode":"                // never see the sentinel.\n                return JsArray.unwrapHole(list.get(i));\n            }\n            if (object instanceof String s) {\n                if (i < 0 || i >= s.length()) return Terms.UNDEFINED;\n                return s.substring(i, i + 1);\n            }\n            if (object instanceof byte[] bytes) {\n                if (i < 0 || i >= bytes.length) return Terms.UNDEFINED;\n                return bytes[i] & 0xFF;\n            }\n            ObjectLike converted = Terms.toObjectLike(object);\n            if (converted instanceof JsArray jsArray) {\n                return jsArray.getIndexedValue(i, jsArray, context);\n            }\n            if (object instanceof Map || object instanceof ObjectLike) {\n                return getByName(object, Terms.toPropertyKey(index), optional, context, functionCall);\n            }\n            throw JsErrorException.typeError(\"get by index [\" + i + \"] for non-array: \" + object);\n        }\n        return getByName(object, Terms.toPropertyKey(index), optional, context, functionCall);\n    }\n\n    private static Object getByName(Object object, String name, boolean optional,\n                                     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","sourceCodeStart":894,"sourceCodeEnd":930,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java#L894-L930","documentation":"Thrown by Karate's `get by index` path when an index-style access is applied to a value that is neither a JsArray/List nor a Map/ObjectLike — e.g. a string, number, or boolean. Arrays and maps support `[i]` lookups; anything else has no indexed value, so the engine raises a TypeError naming the offending value.","triggerScenarios":"Expressions like `response[0]` where `response` is a scalar/string, or `get by index` on a non-collection JSON value; also `karate.get('x[0]')` style access where `x` resolved to a primitive.","commonSituations":"Assuming an API field is an array when it is a string or object, indexing a JSON path result that pointed at a leaf value, schema drift between expected and actual payload shapes (array vs single object).","solutions":["Verify the actual type of the value (print it or match it against `#array`/`#object`/`#string`) before indexing.","Fix the JSON path or expression so it selects the collection, not a leaf.","Convert/unwrap the value first if it is a single object that should be a one-element list (e.g. `* def list = karate.sizeOf(x) != null ? x : [x]`).","Use schema matching (`match each`, `##[] array`) to catch shape drift early."],"exampleFix":"// before (name is a string)\n* match response.name[0] == 'x'\n// after\n* match response.name == 'x'\n// or if it can be either:\n* match response.name == '#(karate.sizeOf(response.name) != null ? response.name[0] : response.name)'","handlingStrategy":"validation","validationCode":"* match response.field == '#array' // or '#object' / '#string' before indexing","typeGuard":"function canIndex(v) { return v instanceof Array || (v && typeof v === 'object'); }","tryCatchPattern":null,"preventionTips":["Assert payload shapes with Karate fuzzy markers before indexed access.","Never index fields you haven't typed; print suspicious values during debugging.","Handle API responses that return a single object instead of an array.","Keep JSON schema definitions next to the feature and validate early."],"tags":["javascript","type-error","array-index","wrong-type"],"backgroundTag":"incompatible-source-type","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"}