karatelabs/karate · error · RuntimeException

Failed to read bytes from

Error message

Failed to read bytes from: ${path}

What it means

After resolving the path, readAsBytes() opens the resource stream and reads all bytes; if the underlying IO fails with an IOException, Karate wraps it in this message including the path and the original cause. It means the file was resolved but its bytes could not be read (missing file, unreadable stream, IO error).

Solutions

  1. Verify the file exists at the given path/classpath location (print it or list the directory).
  2. Fix the path prefix (classpath:, file:, relative) so resolution points at the right root.
  3. Ensure the resource is included in the build (test resources packaging) when running from a jar.
  4. Check file read permissions for the process user.

Example fix

// before
var bytes = karate.readAsBytes('classpath:files/repot.pdf');
// after
var bytes = karate.readAsBytes('classpath:files/report.pdf');
Defensive patterns

Strategy: try-catch

Validate before calling

var path = 'classpath:files/report.pdf';
// verify presence before reading
var exists = karate.readAsString('classpath:files/manifest.txt') != null; // or list assets in config

Try / catch

var bytes;
try { bytes = karate.readAsBytes(path); }
catch (e) { if ((e.message || '').indexOf('Failed to read bytes from') >= 0) karate.fail('resource missing/unreadable: ' + path); throw e; }

Prevention

When it happens

Trigger: karate.readAsBytes('...') where the resource stream throws IOException — typically the file does not exist at the resolved location, the path is wrong, or the file is unreadable/locked.

Common situations: Typo'd classpath paths; file present in dev but not packaged into the test classpath jar; permissions issues in CI containers.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/22e5b52afbfae471. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJs.java:502

            Object fallback = args.length > 1 ? args[1] : null;
            Object first = args[0];
            if (first == null) return fallback;
            String value = getProperty(first.toString());
            return (value == null || value.isEmpty()) ? fallback : value;
        };
    }

    private JavaInvokable readAsBytes() {
        return args -> {
            if (args.length == 0) {
                throw new RuntimeException("readAsBytes() needs at least one argument");
            }
            String path = args[0] + "";
            Resource resource = getCurrentResource().resolve(path);
            try (java.io.InputStream is = resource.getStream()) {
                return is.readAllBytes();
            } catch (java.io.IOException e) {
                throw new RuntimeException("Failed to read bytes from: " + path, e);
            }
        };
    }

    private JavaInvokable get() {
        return args -> {
            if (args.length == 0) {
                throw new RuntimeException("get() needs at least one argument");
            }
            String expr = args[0] + "";

            Object result;
            // a $-prefix always means a path expression, never a variable name - isSimpleIdentifier
            // accepts '$' as a leading char, so without this `karate.get('$x')` would hunt for a
            // variable literally called "$x" instead of resolving the bare `$varname` form
            if (!expr.startsWith("$") && isSimpleIdentifier(expr)) {
                result = engine.get(expr);
            } else {

View on GitHub (pinned to a22eb90246)