karatelabs/karate · error · IllegalArgumentException

boot.classpath(' '): expected a directory RELATIVE to the…

Error message

boot.classpath('${dir}'): expected a directory RELATIVE to the project root (e.g. 'src/test/resources'), not an absolute or prefixed reference

What it means

boot.classpath(dir) only accepts a directory path relative to the project root. Paths with file:, classpath:, or this: prefixes, or absolute paths (leading '/' or a Windows drive letter), are rejected with an IllegalArgumentException because the boot classpath mapping is by definition project-root-relative.

Solutions

  1. Strip the prefix and make the path relative to the project root, e.g. boot.classpath('src/test/resources').
  2. Use '' if the intended directory is the project root itself.
  3. For host-absolute locations, move/link the resources inside the project instead of pointing boot.classpath outside it.

Example fix

// before
boot.classpath('file:/home/me/proj/src/test/resources');
// after
boot.classpath('src/test/resources');
Defensive patterns

Strategy: validation

Validate before calling

// before calling boot.classpath(dir)
assert dir != null && !dir.startsWith("file:") && !dir.startsWith("classpath:")
    && !dir.startsWith("this:") && !dir.startsWith("/")
    && !java.nio.file.Path.of(dir).isAbsolute()
    : "boot.classpath expects a project-relative directory";

Prevention

When it happens

Trigger: Calling boot.classpath('file:/abs/path'), boot.classpath('classpath:foo'), boot.classpath('this:dir'), boot.classpath('/etc/somewhere'), or boot.classpath('C:\\tools\\res') — any prefixed or absolute reference.

Common situations: Reusing a classpath-style resource string in the boot config; hard-coding an absolute machine path that breaks portability; converting an old file: based read into a boot.classpath call without stripping the prefix.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/BootBinding.java:156

     * re-anchors to. One committed line makes a Maven/Gradle project resolve its references
     * identically under a JVM run — where the classloader hits and this mapping stays inert — and
     * under a bare-folder serve run, where the fallback carries {@code classpath:} refs to the
     * declared dir.
     *
     * <p>The argument is a <b>root-relative reference</b>, so {@code file:} / {@code classpath:} /
     * {@code this:} and Windows drive-letter absolutes are rejected. {@code ''} is valid and means
     * the root itself (the "unify only, map nothing" spelling) — which is also what an undeclared
     * project gets, so a bare-folder project never needs this call. Last call wins.</p>
     */
    public void classpath(String dir) {
        if (dir == null) {
            throw new IllegalArgumentException("boot.classpath: dir is null — pass a project-relative "
                    + "directory such as 'src/test/resources', or '' for the project root");
        }
        if (dir.startsWith(Resource.FILE_COLON) || dir.startsWith(Resource.CLASSPATH_COLON)
                || dir.startsWith(Resource.THIS_COLON)
                || (!dir.startsWith("/") && java.nio.file.Path.of(dir).isAbsolute())) {
            throw new IllegalArgumentException("boot.classpath('" + dir + "'): expected a directory "
                    + "RELATIVE to the project root (e.g. 'src/test/resources'), not an absolute or "
                    + "prefixed reference");
        }
        this.classpathDir = Resource.stripLeadingSlashes(dir);
    }

    /**
     * The directory declared by {@link #classpath(String)}, root-relative and de-slashed, or
     * {@code null} when the project declared nothing (then the fallback dir IS the root).
     */
    public String getClasspathDir() {
        return classpathDir;
    }

    /**
     * {@code boot.read('path')} — read a text file, on the one unified rule: a leading {@code /}
     * anchors THE project root, a bare ref is root-relative, {@code classpath:} is
     * classloader-first then the {@link #classpath(String)} fallback, and {@code file:} is a host

View on GitHub (pinned to a22eb90246)