kestra-io/kestra · error · IllegalArgumentException

Cannot process the URI %s: scheme not supported.

Error message

Cannot process the URI %s: scheme not supported.

What it means

Thrown by the 'fileExists' function when the resolved URI's scheme does not match kestra:// (StorageContext.KESTRA_SCHEME), the local file:// scheme (LocalPath.FILE_SCHEME), or the namespace file scheme (Namespace.NAMESPACE_FILE_SCHEME). The switch covers only those three; anything else falls to default and throws IllegalArgumentException, which the parent class surfaces using getErrorMessage().

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/FileExistsFunction.java:30

import io.pebbletemplates.pebble.template.EvaluationContext;
import jakarta.inject.Singleton;

@Singleton
public class FileExistsFunction extends AbstractFileFunction {
    public static final String NAME = "fileExists";
    private static final String ERROR_MESSAGE = "The 'fileExists' function expects an argument 'path' that is a path to the internal storage URI.";

    @Override
    protected Object fileFunction(EvaluationContext context, URI path, String namespace, String tenantId, Map<String, Object> args) throws IOException {
        return switch (path.getScheme()) {
            case StorageContext.KESTRA_SCHEME -> storageInterface.get().exists(tenantId, namespace, path);
            case LocalPath.FILE_SCHEME -> localPathFactory.get().createLocalPath().exists(path);
            case Namespace.NAMESPACE_FILE_SCHEME -> {
                Namespace namespaceStorage = namespaceFactory.get().of(tenantId, namespace, storageInterface.get());
                yield namespaceStorage.exists(NamespaceFile.normalize(Path.of(path.getPath())));
            }
            default -> throw new IllegalArgumentException(SCHEME_NOT_SUPPORTED_ERROR.formatted(path));
        };
    }

    @Override
    protected String getErrorMessage() {
        return ERROR_MESSAGE;
    }
}

View on GitHub (pinned to 823fada927)

Solutions

  1. Use a kestra:// internal storage URI (e.g. from a task output) for files stored in Kestra's internal storage.
  2. Use the namespace file scheme for files in the namespace files storage.
  3. Use file:// with a local path only in worker contexts that support it.
  4. If you need to check an external URL, fetch it first into internal storage and then call fileExists() on the resulting kestra:// URI.

Example fix

# before
exists: "{{ fileExists('https://example.com/data.csv') }}"
# after - reference internal storage
exists: "{{ fileExists(outputs.write.outputFiles['data.csv']) }}"
Defensive patterns

Strategy: validation

Validate before calling

# Validate the URI scheme before calling fileExists(). Allowed: kestra://, file:// (local), and the namespace file scheme.
# {{ (uri starts with 'kestra://' or uri starts with 'file://' or uri starts with 'namespace://') ? fileExists(uri) : false }}

Prevention

When it happens

Trigger: Passing fileExists() a URI like http://..., s3://..., gs://..., ftp://..., or a bare relative path that resolves to an unexpected scheme; passing an absolute filesystem path that does not map to the local file scheme.

Common situations: Confusing internal storage URIs with external URLs; using a plugin-specific storage URI; forgetting the kestra:// or namespace:// prefix; pasting a public URL instead of an internal storage reference.

Related errors


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