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

  1. Provide the path argument: {{ read('kestra:///namespace/flow/executions/.../file') }} or {{ read(outputs.download.uri) }}.
  2. Ensure the variable feeding path is defined and non-null.
  3. 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

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


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/b9f086e69f42d87c. Report an issue: GitHub.