kestra-io/kestra · error · IllegalArgumentException

Scheme not supported

Error message

Scheme not supported: {}

What it means

Thrown by URIFetcher.fetchInputStream()'s switch on uri.getScheme() when the scheme passed the constructor's SUPPORTED_SCHEMES check at deserialization but the runtime RunContext does not provide a reader for it, OR more commonly when a URIFetcher is built bypassing the constructor (e.g., from an already-open URI). The default branch is a defensive fallback for any scheme not matching kestra/file/namespace. Unlike error 29, this fires at fetch time, not construction time, and the message omits the supported list.

Solutions

  1. Always construct URIFetcher via new URIFetcher(uri) or URIFetcher.of(uri) so the constructor validates the scheme.
  2. Confirm the scheme exactly matches one of: kestra, file, namespace (lowercase).
  3. If adding a new scheme, update BOTH SUPPORTED_SCHEMES and the switch statement.

Example fix

// before (bypasses constructor guard)
URIFetcher f = new URIFetcher(URI.create("ftp://h/data")); // may pass if ftp were in list but not switch
f.fetchInputStream(ctx); // default -> throw

// after
new URIFetcher(URI.create("kestra:///data")).fetchInputStream(ctx);
Defensive patterns

Strategy: try-catch

Validate before calling

String scheme = uri.getScheme();
if (!Set.of(StorageContext.KESTRA_SCHEME, LocalPath.FILE_SCHEME, Namespace.NAMESPACE_FILE_SCHEME).contains(scheme)) {
    throw new IllegalArgumentException("Scheme not supported: " + scheme);
}

Try / catch

try {
    fetcher.fetchInputStream(runContext);
} catch (IllegalArgumentException e) {
    log.error("Unsupported scheme at fetch time: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: A URIFetcher instance is constructed via a path that skips the scheme validation, then fetchInputStream is called; a custom scheme is injected at runtime; the scheme string differs in case or whitespace from the expected constants.

Common situations: Reflection or test code builds a URIFetcher directly; a serialized URIFetcher round-trips through a format that drops the constructor guard; future scheme additions create an inconsistency between SUPPORTED_SCHEMES and the switch branches.

Related errors


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

Appendix: source

Thrown at core/src/main/java/io/kestra/core/models/property/URIFetcher.java:97

     *
     * @throws IOException if an IO error occurs
     * @throws SecurityException if the URI points to a path that is not allowed
     */
    public InputStream fetch(RunContext runContext) throws IOException {
        if (uri == null) {
            return InputStream.nullInputStream();
        }

        // we need to first check the protocol, then create one reader by protocol
        return switch (uri.getScheme()) {
            case StorageContext.KESTRA_SCHEME -> runContext.storage().getFile(uri);
            case LocalPath.FILE_SCHEME -> runContext.localPath().get(uri);
            case Namespace.NAMESPACE_FILE_SCHEME -> {
                var namespace = uri.getAuthority() == null ? runContext.storage().namespace() : runContext.storage().namespace(uri.getAuthority());
                var nsFileUri = namespace.get(Path.of(uri.getPath())).uri();
                yield runContext.storage().getFile(nsFileUri);
            }
            default -> throw new IllegalArgumentException("Scheme not supported: " + uri.getScheme());
        };
    }
}

View on GitHub (pinned to 823fada927)