{"record":{"id":"c3838e84be7ea0e9","repo":"kestra-io/kestra","slug":"the-fromion-function-expects-an-argument-ion","errorCode":null,"errorMessage":"The 'fromIon' function expects an argument 'ion'.","messagePattern":"The 'fromIon' function expects an argument 'ion'\\.","errorType":"validation","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/FromIonFunction.java","lineNumber":36,"sourceCode":"public class FromIonFunction implements KestraFunction {\n    public static final String NAME = \"fromIon\";\n\n    public List<String> getArgumentNames() {\n        return List.of(\"ion\", \"allRows\");\n    }\n\n    @Override\n    public Map<String, String> getArgumentDefaults() {\n        HashMap<String, String> defaults = new HashMap<>();\n        defaults.put(\"ion\", ReadFileFunction.NAME + \"('ion/namespace/file')\");\n        defaults.put(\"allRows\", null);\n        return defaults;\n    }\n\n    @Override\n    public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {\n        if (!args.containsKey(\"ion\")) {\n            throw new PebbleException(null, \"The 'fromIon' function expects an argument 'ion'.\", lineNumber, self.getName());\n        }\n\n        Object ionArg = args.get(\"ion\");\n        if (ionArg == null) {\n            return null;\n        }\n\n        byte[] ionBytes;\n        if (ionArg instanceof byte[] bytes) {\n            ionBytes = bytes;\n        } else if (ionArg instanceof String str) {\n            ionBytes = str.getBytes(StandardCharsets.UTF_8);\n        } else {\n            throw new PebbleException(null, \"The 'fromIon' function expects an argument 'ion' with type string or byte[].\", lineNumber, self.getName());\n        }\n\n        boolean allRows = args.containsKey(\"allRows\") ? (Boolean) args.get(\"allRows\") : false;\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/FromIonFunction.java#L18-L54","documentation":"Thrown by the 'fromIon' function when the args map does not contain the 'ion' entry. The function parses Kestra Ion data (the row-oriented serialization used by task outputs); 'ion' is the single required argument. A later, separate check handles a null ion value (returns null) and a wrong-type value, so this guard only covers the absence of the key.","triggerScenarios":"Calling fromIon() with no arguments, fromIon(someOther='x'), or misspelling the argument so Pebble does not bind it to 'ion'.","commonSituations":"Forgetting the argument after autocompleting from getArgumentDefaults(); renaming 'ion'; assuming the function reads a file path directly (it takes already-read Ion content, often via readFile()).","solutions":["Provide the 'ion' argument, typically the output of readFile() on an Ion file: fromIon(readFile(outputs.task.outputFiles['data.ion'])).","If using named arguments, spell it exactly as 'ion'.","Make sure the expression feeding 'ion' actually resolves to Ion content (string or bytes), not a file path or null."],"exampleFix":"# before\nrows: \"{{ fromIon() }}\"\n# after\nrows: \"{{ fromIon(readFile('ion/namespace/file')) }}\"","handlingStrategy":"validation","validationCode":"# Ensure the 'ion' argument is provided before calling fromIon().\n# {{ (ionContent != null) ? fromIon(ionContent) : null }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass the 'ion' argument, typically via readFile() of an Ion file.","Spell the argument exactly as 'ion'.","Confirm the expression resolves to Ion content, not a path.","Remove getArgumentDefaults() placeholders before production."],"tags":["pebble","fromion","serialization","ion","validation","missing-argument"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}