{"record":{"id":"db2f38f4b8f76e7a","repo":"karatelabs/karate","slug":"index-index-size-size","errorCode":null,"errorMessage":"index: ${index}, size: ${size}","messagePattern":"index: (.+?), size: (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/match/DiskBackedList.java","lineNumber":182,"sourceCode":"    private static Object deserializeItem(String json) {\n        if (json == null || json.isEmpty() || \"null\".equals(json)) {\n            return null;\n        }\n        return JSONValue.parse(json);\n    }\n\n    @Override\n    public int size() {\n        return size;\n    }\n\n    @Override\n    public Object get(int index) {\n        if (closed) {\n            throw new IllegalStateException(\"store has been closed\");\n        }\n        if (index < 0 || index >= size) {\n            throw new IndexOutOfBoundsException(\"index: \" + index + \", size: \" + size);\n        }\n        try {\n            if (raf == null) {\n                raf = new RandomAccessFile(tempFile, \"r\");\n            }\n            long offset = lineOffsets.get(index);\n            raf.seek(offset);\n            String line = raf.readLine();\n            return deserializeItem(line);\n        } catch (IOException e) {\n            throw new RuntimeException(\"failed to read item at index \" + index, e);\n        }\n    }\n\n    @Override\n    public Iterator<Object> iterator() {\n        if (closed) {\n            throw new IllegalStateException(\"store has been closed\");","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/match/DiskBackedList.java#L164-L200","documentation":"Bounds check in DiskBackedList.get(): the requested index is outside the valid range [0, size), where size is the number of items backed by the on-disk store. Fires on negative or >= size indexes; standard IndexOutOfBoundsException, not a storage failure.","triggerScenarios":"Calling get() with an index from a stale size snapshot while the list was cleared or truncated; arithmetic errors producing negative indexes; concurrent modification where one thread removes items while another indexes.","commonSituations":"Loop conditions using a cached size; off-by-one in pagination code; iterating with manual index math instead of the iterator.","solutions":["Clamp indexes: only call get(i) for 0 <= i < list.size()","Re-read size() immediately before indexed access instead of caching it","Use the iterator or for-each loop instead of manual index arithmetic","Synchronize access if the list is mutated concurrently"],"exampleFix":"// before\nfor (int i = 0; i < cachedSize; i++) use(list.get(i));\n// after\nfor (int i = 0; i < list.size(); i++) use(list.get(i));","handlingStrategy":"validation","validationCode":"if (index < 0 || index >= list.size()) throw new IndexOutOfBoundsException(\"index: \" + index + \", size: \" + list.size());","typeGuard":"boolean inRange(int i, List<?> l) { return i >= 0 && i < l.size(); }","tryCatchPattern":"try { return list.get(i); } catch (IndexOutOfBoundsException e) { log.warn(\"bad index {} vs size {}\", i, list.size()); return null; }","preventionTips":["Always bound-check against the live size(), not a cached value","Prefer iterators over manual indexing","Synchronize concurrent mutation and reads"],"tags":["index-out-of-bounds","collections","validation"],"backgroundTag":"index-out-of-bounds","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"}