{"record":{"id":"b8671c10621e6536","repo":"apple/pkl","slug":"cannotiterateoverthisvalue","errorCode":"cannotIterateOverThisValue","errorMessage":"Cannot iterate over value of type `{0}`.","messagePattern":"Cannot iterate over value of type `(.+?)`\\.","errorType":"exception","errorClass":"VmException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/expression/generator/GeneratorForNode.java","lineNumber":144,"sourceCode":"    var length = iterable.getLength();\n    for (long key = 0, value = iterable.start; key < length; key++, value += iterable.step) {\n      executeIteration(frame, parent, data, key, value);\n    }\n  }\n\n  @Specialization\n  protected void eval(VirtualFrame frame, Object parent, ObjectData data, VmBytes iterable) {\n    long idx = 0;\n    for (var byt : iterable.getBytes()) {\n      executeIteration(frame, parent, data, idx++, (long) byt);\n    }\n  }\n\n  @Fallback\n  @SuppressWarnings(\"unused\")\n  protected void fallback(VirtualFrame frame, Object parent, ObjectData data, Object iterable) {\n    CompilerDirectives.transferToInterpreter();\n    throw exceptionBuilder()\n        .evalError(\"cannotIterateOverThisValue\", VmUtils.getClass(iterable))\n        .withLocation(iterableNode)\n        .withProgramValue(\"Value\", iterable)\n        .build();\n  }\n\n  private void doEvalObject(VirtualFrame frame, VmObject iterable, Object parent, ObjectData data) {\n    iterable.forceAndIterateMemberValues(\n        (key, member, value) -> {\n          var convertedKey = member.isProp() ? key.toString() : key;\n          // TODO: Executing iteration behind a Truffle boundary is bad for performance.\n          // This and similar cases will be fixed in an upcoming PR that replaces method\n          // `(forceAnd)iterateMemberValues` with cursor-based external iterators.\n          executeIteration(frame, parent, data, convertedKey, value);\n          return true;\n        });\n  }\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/expression/generator/GeneratorForNode.java#L126-L162","documentation":"Thrown when a generator's `for` expression tries to iterate a value that is not iterable (not a List, Set, Map, String, Listing, Mapping, etc.). The `@Fallback` node catches any value the specialized iterable nodes cannot handle and reports the value's type.","triggerScenarios":"`for (x in expr)` where `expr` evaluates to a non-iterable value — e.g. an Int, Boolean, a class instance, or a module object instead of a collection. Raised in the `fallback` node of GeneratorForNode.","commonSituations":"Iterating over a property that is a scalar (`for (p in person.name)`); forgetting that a nullable or default value resolved to `null`/Int instead of a List; iterating a module or class reference instead of one of its collections.","solutions":["Check the type of the iterated expression; wrap scalars in a list (`[expr]`) if iteration over a single value is intended.","Use the nullish/type check pattern: only iterate when the value is a collection (e.g. `person.names.toList()`).","Inspect the 'Value' attached to the error message to see the actual runtime value and correct the expression."],"exampleFix":"// before\nfor (tag in contact.tags) { ... } // tags may be a single String\n// after\nfor (tag in contact.tags.toList()) { ... }","handlingStrategy":"type-guard","validationCode":"// Pkl: guard before iterating\nwhen (value is List || value is Set || value is Listing) {\n  for (x in value) { ... }\n}","typeGuard":"function isIterable(v: Any): Boolean =\n  v is List || v is Set || v is Map || v is Listing || v is Mapping || v is String","tryCatchPattern":null,"preventionTips":["Check the property's declared/defaulted type before `for`-ing over it.","Convert single values with `[v].toList()` when a scalar-or-collection union is possible.","Use `v is Collection` style checks in `when` guards."],"tags":["pkl","iteration","type-mismatch","for-loop"],"backgroundTag":"type-mismatch","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}