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

The read() Pebble function accepts a path argument and dispatches on the URI scheme to the correct storage backend. Supported schemes are 'kestra://' (internal storage), 'file://' (local files, requires LocalFiles enabled), and 'nsfile://' (namespace files). Any other scheme (e.g., http://, https://, s3://, ftp://) reaches the default branch and throws IllegalArgumentException, which is caught upstream and re-wrapped as a PebbleException. The same constant is also thrown from AbstractFileFunction when a string path matches the generic URI pattern but is none of the recognized schemes.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/ReadFileFunction.java:65

    @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 -> {
                try (InputStream inputStream = storageInterface.get().get(tenantId, namespace, path)) {
                    yield readContent(inputStream);
                }
            }
            case LocalPath.FILE_SCHEME -> {
                try (InputStream inputStream = localPathFactory.get().createLocalPath().get(path)) {
                    yield readContent(inputStream);
                }
            }
            case Namespace.NAMESPACE_FILE_SCHEME -> {
                try (InputStream inputStream = contentInputStream(path, namespace, tenantId, args)) {
                    yield readContent(inputStream);
                }
            }
            default -> throw new IllegalArgumentException(SCHEME_NOT_SUPPORTED_ERROR.formatted(path));
        };
    }

    // Returns byte[] for binary ION (preserves fidelity for fromIon()), String for everything else
    private static Object readContent(InputStream inputStream) throws IOException {
        byte[] bytes = inputStream.readAllBytes();
        if (IonStreamUtils.isIonBinary(bytes)) {
            return bytes;
        }
        return new String(bytes, StandardCharsets.UTF_8);
    }

    private InputStream contentInputStream(URI path, String namespace, String tenantId, Map<String, Object> args) throws IOException {
        Namespace namespaceStorage = namespaceFactory.get().of(tenantId, namespace, storageInterface.get());

        if (args.containsKey(REVISION)) {
            return namespaceStorage.getFileContent(
                NamespaceFile.normalize(Path.of(path.getPath())),

View on GitHub (pinned to 823fada927)

Solutions

  1. Use a plugin task (e.g., io.kestra.plugin.core.http.Download) to fetch remote URLs into internal storage, then pass the resulting kestra:// URI to read().
  2. For namespace files, use a plain relative path or the 'nsfile://' scheme: {{ read('nsfile:///path/to/file') }}.
  3. For internal storage outputs, pass the raw output URI variable (e.g., {{ outputs.download.uri }}) which is already kestra://.
  4. Check that the path variable does not contain a scheme prefix when you intend a namespace-file relative path.

Example fix

# before — unsupported scheme
- id: read_remote
  type: io.kestra.plugin.core.log.Log
  message: "{{ read('https://example.com/data.json') }}"

# after — download to internal storage, then read
- id: download
  type: io.kestra.plugin.core.http.Download
  uri: "https://example.com/data.json"
- id: read_downloaded
  type: io.kestra.plugin.core.log.Log
  message: "{{ read(outputs.download.uri) }}"
Defensive patterns

Strategy: validation

Validate before calling

# Before calling read(), verify the path scheme is supported.
# Supported: kestra://, file:// (if LocalFiles enabled), nsfile://, or plain relative paths.
{% set supported = path starts with 'kestra://' or path starts with 'nsfile://' or path starts with 'file://' or not path matches '^[a-zA-Z][a-zA-Z0-9+.-]*:.*' %}
{% if supported %}{{ read(path) }}{% else %}UNSUPPORTED_SCHEME{% endif %}

Prevention

When it happens

Trigger: Calling {{ read('https://example.com/file.txt') }}, {{ read('s3://bucket/key') }}, or any path with an unknown scheme. Also triggered when a variable that was expected to hold a kestra:// URI or a plain relative path instead contains a fully-qualified URL with an unsupported scheme.

Common situations: A flow output URI from an external system (e.g., an HTTP download task) is passed to read() without converting it to internal storage first. Misconfiguring a path variable that accidentally includes an 'http://' or custom scheme prefix. Using read() when you actually need an HTTP fetch or a plugin-specific download.

Related errors


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