kestra-io/kestra · error · PebbleException
getErrorMessage() [abstract: subclass-defined ERROR_MESSAGE]
Error message
getErrorMessage() [abstract: subclass-defined ERROR_MESSAGE]
What it means
AbstractFileFunction is the shared base for the 'read'/'fileExists' Pebble functions (and similar). The abstract getErrorMessage() returns a subclass-specific message used when the required 'path' argument is missing. The throw at execute() happens when args does not contain the 'path' key. The concrete message depends on the subclass (e.g. "The 'read' function expects an argument 'path'.").
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/AbstractFileFunction.java:65
protected Provider<NamespaceFactory> namespaceFactory;
@Inject
protected LocalFilesConfiguration localFilesConfiguration;
// @Value("${kestra.server-type:}") // default to empty as tests didn't set this property
// private String serverType;
@SuppressWarnings("unchecked")
@Override
public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
// TODO it will be enabled on the next release so the code is kept commented out
// don't forget to also re-enabled the test
// if (!calledOnWorker()) {
// throw new PebbleException(null, "The 'read' function can only be used in the Worker as it access the internal storage.", lineNumber, self.getName());
// }
if (!args.containsKey(PATH)) {
throw new PebbleException(null, getErrorMessage(), lineNumber, self.getName());
}
Object path = args.get(PATH);
try {
URI fileUri;
String namespace;
Map<String, String> flow = (Map<String, String>) context.getVariable("flow");
String tenantId = flow.get(TENANT_ID);
if (path instanceof URI uri) {
fileUri = uri;
namespace = checkAllowedFileAndReturnNamespace(context, fileUri);
} else if (path instanceof String str) {
if (str.startsWith(KESTRA_SCHEME)) {
fileUri = URI.create(str);
namespace = checkAllowedFileAndReturnNamespace(context, fileUri);
} else if (str.startsWith(LocalPath.FILE_PROTOCOL)) {View on GitHub (pinned to 823fada927)
Solutions
- Provide the path argument: {{ read('kestra:///namespace/flow/executions/.../file') }} or {{ read(outputs.download.uri) }}.
- Ensure the variable feeding path is defined and non-null.
- Use the documented default (outputs.download.uri) by passing path explicitly rather than relying on omission.
Example fix
// before
{{ read() }}
// after
{{ read(path=outputs.download.uri) }} Defensive patterns
Strategy: validation
Validate before calling
// Pebble: always pass path, ideally from a task output
{{ read(path=(outputs.download.uri ?? 'kestra:///namespace/flow/executions/' ~ execution.id ~ '/tasks/t1/' ~ taskrun.id ~ '/default.ion')) }} Prevention
- Always pass the 'path' argument explicitly.
- Prefer URIs emitted by task outputs over hand-built strings.
- Use the expression editor to confirm path resolves before saving.
When it happens
Trigger: Calling read() with no argument: {{ read() }}; calling with only a different argument name; calling with a variable that resolves to an absent value so 'path' is never bound.
Common situations: Refactoring a template and dropping the path argument; using a positional form that a Pebble version does not bind; typo in the argument name.
Related errors
- Cannot process the URI %s: scheme not supported.
- Unable to read the file {path}
- IOException|IllegalArgumentException: e.getMessage()
- You cannot set a namespace both as the function argument and
- Unable to read the file '{path}' as it is not an execution f
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/b9f086e69f42d87c.
Report an issue: GitHub.