{"record":{"id":"6a8ffb655e799e00","repo":"pentaho/pentaho-kettle","slug":"jdbcdriverresolver-not-a-jar-file-jarabsolutepath","errorCode":null,"errorMessage":"JdbcDriverResolver: not a JAR file: \" + jarAbsolutePath","messagePattern":"JdbcDriverResolver: not a JAR file: \" \\+ jarAbsolutePath","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/JdbcDriverResolver.java","lineNumber":402,"sourceCode":"    return Files.isRegularFile( Paths.get( path ) );\n  }\n\n  /**\n   * Converts an absolute JAR path to a {@link URL}, validating that the file exists\n   * and has a {@code .jar} extension.\n   *\n   * @param jarAbsolutePath absolute path to the JAR file\n   * @return the file URL\n   * @throws KettleDatabaseException if the file does not exist, is not a regular file,\n   *                                  does not end with .jar, or cannot be converted\n   */\n  private static URL toJarUrl( String jarAbsolutePath ) throws KettleDatabaseException {\n    File jarFile = new File( jarAbsolutePath );\n    if ( !jarFile.exists() || !jarFile.isFile() ) {\n      throw new KettleDatabaseException( \"JdbcDriverResolver: JAR not found: \" + jarAbsolutePath );\n    }\n    if ( !jarFile.getName().toLowerCase().endsWith( \".jar\" ) ) {\n      throw new KettleDatabaseException( \"JdbcDriverResolver: not a JAR file: \" + jarAbsolutePath );\n    }\n    try {\n      return jarFile.toPath().toUri().toURL();\n    } catch ( Exception e ) {\n      throw new KettleDatabaseException( \"JdbcDriverResolver: Cannot convert path to URL: \" + jarAbsolutePath, e );\n    }\n  }\n}\n","sourceCodeStart":384,"sourceCodeEnd":411,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/JdbcDriverResolver.java#L384-L411","documentation":"toJarUrl() additionally validates that the file name ends with .jar (case-insensitive). A path that exists but is not a JAR (e.g. a directory-named path, a .zip, or a class file) is rejected with this KettleDatabaseException.","triggerScenarios":"Passing a driverId containing a path/extension such that the resolved file is not a *.jar — e.g. driverId 'mylib' resolving a file 'mylib' (no extension), or a path pointing to a directory-like regular file or a .zip driver.","commonSituations":"Users configuring a full JAR path already containing '.jar' so the resolver builds 'foo.jar.jar'-style or non-jar artifacts; pointing the drivers directory at files with .zip extension; misconfigured driverId from database types.","solutions":["Ensure the file at jarAbsolutePath is a real .jar file (rename or re-download it)","Pass only the driverId (without extension) — resolve() appends '.jar' itself","Inspect what file exists at the path in the message; remove or replace non-jar artifacts"],"exampleFix":"// before\nString path = JdbcDriverResolver.resolve( \"/opt/drivers/postgresql-42.jar\" ); // yields .jar.jar naming issues\n// after\nString path = JdbcDriverResolver.resolve( \"postgresql-42\" );","handlingStrategy":"validation","validationCode":"File f = new File( path );\nif ( !f.getName().toLowerCase().endsWith( \".jar\" ) ) throw new IllegalArgumentException( \"not a .jar: \" + path );","typeGuard":"boolean isJarFile( String p ) { return new File( p ).getName().toLowerCase().endsWith( \".jar\" ); }","tryCatchPattern":"try { toJarUrl( path ); } catch ( KettleDatabaseException e ) { if ( e.getMessage().contains( \"not a JAR file\" ) ) fixExtensionOrReplace( path ); throw e; }","preventionTips":["Pass bare driverIds, not pre-built paths","Keep only .jar artifacts in the drivers directory","Never rename driver artifacts to other extensions"],"tags":["jdbc","validation","file"],"backgroundTag":"invalid-argument-value","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}