{"record":{"id":"b8303c0252063f28","repo":"kestra-io/kestra","slug":"found-a-null-value-in-the-ion-file","errorCode":null,"errorMessage":"Found a null value in the ION file","messagePattern":"Found a null value in the ION file","errorType":"exception","errorClass":"IllegalVariableEvaluationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/FlowableUtils.java","lineNumber":587,"sourceCode":"        try (var is = new BufferedInputStream(URIFetcher.of(uri).fetch(runContext), FileSerde.BUFFER_SIZE)) {\n            List<String> result = new ArrayList<>(count);\n            long[] index = { 0 };\n            FileSerde.read(is, throwConsumer(record ->\n            {\n                if (index[0] >= offset && result.size() < count) {\n                    result.add(ionValueToString(record));\n                }\n                index[0]++;\n            }));\n            return Pair.of(result, offset + result.size());\n        }\n    }\n\n    private static String ionValueToString(Object parsed) throws IllegalVariableEvaluationException {\n        return switch (parsed) {\n            case String s -> s;\n            case Number n -> n.toString();\n            case null -> throw new IllegalVariableEvaluationException(\"Found a null value in the ION file\");\n            default -> serializeAsString(parsed);\n        };\n    }\n}\n","sourceCodeStart":569,"sourceCodeEnd":592,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/FlowableUtils.java#L569-L592","documentation":"Thrown by `ionValueToString` while reading rows from an ION file backing a Loop task's URI-based `values` (see `readLoopValuesFromUri` / `readAndCountLoopValuesFromUri`). Each parsed record is converted to a string; if a record is `null` (an explicit null row in the ION stream), this fires. The ION file is fetched via `URIFetcher` and read with `FileSerde`.","triggerScenarios":"A Loop/ForEach task whose `values` resolves to a URI (e.g. a Kestra internal storage URI or a `file://`/`http://` URI) pointing to an ION-encoded file, and that file contains a null record. ION is Kestra's row format for tabular outputs (queries, reads), so a null row can appear when a source has an empty line or a deserialized null object.","commonSituations":"Iterating over the rows of a SQL query / CSV read where a row serialized as null; a corrupted or partially-written ION file from a crashed upstream task; concatenating ION streams with a trailing null.","solutions":["Inspect and clean the upstream ION-producing task so it never writes a null record.","Re-run the upstream task that generated the URI to regenerate a clean file.","If the URI is a static file you control, edit it to remove null rows.","Use an intermediate task to filter nulls before passing the URI to the Loop."],"exampleFix":"# before — query may emit null rows into the ION file\ntasks:\n  - id: data\n    type: io.kestra.plugin.jdbc.duckdb.Query\n    sql: \"SELECT maybe_null_col FROM t\"\n  - id: loop\n    type: io.kestra.plugin.core.flow.Loop\n    values: \"{{ outputs.data.uri }}\"\n\n# after — coalesce nulls in SQL\n    sql: \"SELECT COALESCE(maybe_null_col, '') AS maybe_null_col FROM t\"","handlingStrategy":"validation","validationCode":"// Validate the ION file has no null rows before looping\ntry (var is = new BufferedInputStream(URIFetcher.of(uri).fetch(runContext), FileSerde.BUFFER_SIZE)) {\n    FileSerde.read(is, throwConsumer(rec -> {\n        if (rec == null) throw new IllegalVariableEvaluationException(\"ION file contains null row at URI \" + uri);\n    }));\n}","typeGuard":null,"tryCatchPattern":"try {\n    FlowableUtils.readLoopValuesFromUri(runContext, uri, offset, count);\n} catch (IllegalVariableEvaluationException e) {\n    if (e.getMessage().equals(\"Found a null value in the ION file\")) {\n        runContext.logger().error(\"ION source at {} has null rows; regenerate or clean it.\", uri);\n    }\n    throw e;\n}","preventionTips":["Ensure upstream SQL/query tasks COALESCE nullable columns before they serialize to ION.","Re-run the producing task if the ION file is suspect.","Validate ION files in a pre-task when the source is external."],"tags":["loop","ion","null","storage","uri"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}