t8y2/dbx · error · IllegalArgumentException

Custom H2 driver profile requires at least one JDBC JAR path

Error message

Custom H2 driver profile requires at least one JDBC JAR path

What it means

H2DriverLoader.loadExternal builds a URLClassLoader from user-supplied JAR paths for a custom H2 driver profile. If the driverPaths list is null or empty there is nothing to load, so it fails fast with IllegalArgumentException instead of silently falling back to a bundled driver.

Source

Thrown at agents/drivers/h2/src/main/java/com/dbx/agent/h2/H2DriverLoader.java:44

        URLClassLoader classLoader = new URLClassLoader(
            new URL[]{jar.toUri().toURL()},
            H2DriverLoader.class.getClassLoader()
        );
        try {
            Driver driver = (Driver) Class.forName("org.h2.Driver", true, classLoader).getDeclaredConstructor().newInstance();
            return new LoadedDriver(version, version.version(), driver, classLoader);
        } catch (Exception error) {
            closeAfterFailure(classLoader, error);
            throw error;
        } catch (LinkageError error) {
            closeAfterFailure(classLoader, error);
            throw error;
        }
    }

    static LoadedDriver loadExternal(List<String> driverPaths, String driverClass) throws Exception {
        if (driverPaths == null || driverPaths.isEmpty()) {
            throw new IllegalArgumentException("Custom H2 driver profile requires at least one JDBC JAR path");
        }
        List<URL> urls = new ArrayList<>();
        List<String> identities = new ArrayList<>();
        for (String driverPath : driverPaths) {
            Path path = Path.of(driverPath).toAbsolutePath().normalize();
            if (!Files.isRegularFile(path)) {
                throw new IOException("Custom H2 JDBC JAR does not exist: " + path);
            }
            urls.add(path.toUri().toURL());
            identities.add(path + ":" + sha256(path));
        }
        String effectiveDriverClass = driverClass == null || driverClass.isBlank() ? "org.h2.Driver" : driverClass.trim();
        URLClassLoader classLoader = new URLClassLoader(
            urls.toArray(new URL[0]),
            H2DriverLoader.class.getClassLoader()
        );
        try {
            Driver driver = (Driver) Class.forName(effectiveDriverClass, true, classLoader).getDeclaredConstructor().newInstance();

View on GitHub (pinned to c0390bff16)

Solutions

  1. Provide at least one JDBC JAR path in the driverPaths list (e.g. /opt/drivers/h2-2.2.224.jar)
  2. Verify the config key/environment variable that supplies the JAR paths is actually set and populated before constructing the profile
  3. If the bundled driver is acceptable, switch the profile from h2-custom to h2/h2-auto instead

Example fix

// before
H2DriverLoader.loadExternal(List.of(), "org.h2.Driver");
// after
H2DriverLoader.loadExternal(List.of("/opt/drivers/h2-2.2.224.jar"), "org.h2.Driver");
Defensive patterns

Strategy: validation

Validate before calling

if (driverPaths == null || driverPaths.isEmpty()) {
    throw new IllegalStateException("h2-custom profile requires at least one JDBC JAR path");
}

Try / catch

try {
    LoadedDriver d = H2DriverLoader.loadExternal(driverPaths, driverClass);
} catch (IllegalArgumentException e) {
    // fall back to bundled profile or surface config error
}

Prevention

When it happens

Trigger: Calling loadExternal (directly or via the h2-custom profile loader) with driverPaths == null, an empty list, or a profile config that declared custom JARs but collected none.

Common situations: Config file with an h2-custom profile but the jdbc-jars/key listing was omitted; environment variable or CLI flag for the JAR path never set; path expansion in a shell yielded nothing (glob with no matches) so the list arrived empty.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/6daa35c9b609c2aa. Report an issue: GitHub.