{"record":{"id":"a1a0e45614237076","repo":"elastic/elasticsearch","slug":"illegal-list-shortcut-value","errorCode":null,"errorMessage":"Illegal list shortcut value [{}].","messagePattern":"Illegal list shortcut value \\[(.+?)\\]\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java","lineNumber":658,"sourceCode":"        }\n\n        // special case: arrays, maps, and lists\n        if (receiverClass.isArray() && \"length\".equals(name)) {\n            // arrays expose .length as a read-only getter\n            return arrayLengthGetter(receiverClass);\n        } else if (Map.class.isAssignableFrom(receiverClass)) {\n            // maps allow access like mymap.key\n            // wire 'key' as a parameter, its a constant in painless\n            return MethodHandles.insertArguments(MAP_GET, 1, name);\n        } else if (List.class.isAssignableFrom(receiverClass)) {\n            // lists allow access like mylist.0\n            // wire '0' (index) as a parameter, its a constant. this also avoids\n            // parsing the same integer millions of times!\n            try {\n                int index = Integer.parseInt(name);\n                return MethodHandles.insertArguments(LIST_GET, 1, index);\n            } catch (NumberFormatException exception) {\n                throw new IllegalArgumentException(\"Illegal list shortcut value [\" + name + \"].\");\n            }\n        }\n\n        throw new IllegalArgumentException(\"dynamic getter [\" + typeToCanonicalTypeName(receiverClass) + \", \" + name + \"] not found\");\n    }\n\n    /**\n     * Looks up handle for a dynamic field setter (field store)\n     * <p>\n     * A dynamic field store for variable {@code x} of type {@code def} looks like:\n     * {@code x.field = y}\n     * <p>\n     * The following field stores are allowed:\n     * <ul>\n     *   <li>Whitelisted {@code field} from receiver's class or any superclasses.\n     *   <li>Whitelisted method named {@code setField()} from receiver's class/superclasses/interfaces.\n     *   <li>The value corresponding to a map key named {@code field} when the receiver is a Map.\n     *   <li>The value in a list at element {@code field} (integer) when the receiver is a List.","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java#L640-L676","documentation":"Def.lookupGetter handles dynamic field reads on 'def'. For a List receiver, the field name must be an integer index (lists allow mylist.0 syntax). The code Integer.parseInt(name) and throws 'Illegal list shortcut value [name]' on NumberFormatException if the name is not parseable as an integer — e.g. mylist.foo where 'foo' is non-numeric.","triggerScenarios":"A Painless script reads a List via dot-shortcut with a non-integer name: def x = [1,2,3]; x.first or x.foo. Maps allow arbitrary string keys (mymap.key), but Lists require integer indices (mylist.0).","commonSituations":"Treating a List like a Map (expecting named access). Confusing list element access patterns. Runtime type of the variable being List when the author assumed Map.","solutions":["Use an integer index for List access: mylist.0 or mylist[0].","If named access is intended, ensure the receiver is a Map, not a List.","Bracket access (mylist[i]) is preferred for dynamic indices."],"exampleFix":"// before\ndef x = [10, 20, 30];\nreturn x.first; // non-numeric shortcut on a List\n// after\nreturn x[0];","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard List dot-access: only allow if name is an integer string\nfunction safeListGet(list, name) {\n  if (!/^-?\\d+$/.test(String(name))) throw new Error(`Use integer index for List; got '${name}'`);\n  return list[Number(name)];\n}","tryCatchPattern":"// Surface 'Illegal list shortcut value' to the script author with guidance to use bracket indexing.","preventionTips":["Use bracket syntax mylist[i] for List element access.","Reserve dot-access for Maps with string keys.","Static-type collections to catch confusion at compile time."],"tags":["painless","script","dynamic-dispatch","def","list","runtime"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}