snowflakedb/snowflake-jdbc

InvalidPathException with 3.13.32 on Windows

Closed this issue · 7 comments

Please answer these questions before submitting your issue.
In order to accurately debug the issue this information is required. Thanks!

  1. What version of JDBC driver are you using?
    3.13.32

  2. What operating system and processor architecture are you using?
    Windows 10 x64

  3. What version of Java are you using?
    openjdk version "17.0.7" 2023-04-18
    OpenJDK Runtime Environment Temurin-17.0.7+7 (build 17.0.7+7)
    OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (build 17.0.7+7, mixed mode, sharing)

  4. What did you do?
    Upgraded a project using v3.13.30 of the driver to v3.13.32. The configuration and project source all remained the same and was working properly with v3.13.30. During startup of the application an InvalidPathException is thrown while attempting to read the sf_client_config.json file.

Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 4: file:\C:\dev\<<snip>>\build\libs\<<snip>>-application.jar!\BOOT-INF\lib\snowflake-jdbc-3.13.32.jar!\sf_client_config.json
        at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77) ~[?:?]
        at sun.nio.fs.WindowsPath.parse(WindowsPath.java:92) ~[?:?]
        at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232) ~[?:?]
        at java.nio.file.Path.of(Path.java:147) ~[?:?]
        at java.nio.file.Paths.get(Paths.java:69) ~[?:?]
        at net.snowflake.client.config.SFClientConfigParser.loadSFClientConfig(SFClientConfigParser.java:44) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.setClientConfig(DefaultSFConnectionHandler.java:128) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initialize(DefaultSFConnectionHandler.java:109) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initializeConnection(DefaultSFConnectionHandler.java:85) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.initConnectionWithImpl(SnowflakeConnectionV1.java:116) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.<init>(SnowflakeConnectionV1.java:96) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:180) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at java.sql.DriverManager.getConnection(DriverManager.java:681) ~[java.sql:?]
        at java.sql.DriverManager.getConnection(DriverManager.java:190) ~[java.sql:?]
        at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:155) ~[spring-jdbc-5.3.26.jar!/:5.3.26]
        at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:146) ~[spring-jdbc-5.3.26.jar!/:5.3.26]
        at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:205) ~[spring-jdbc-5.3.26.jar!/:5.3.26]
        at org.springframework.jdbc.datasource.SingleConnectionDataSource.initConnection(SingleConnectionDataSource.java:224) ~[spring-jdbc-5.3.26.jar!/:5.3.26]
        at org.springframework.jdbc.datasource.SingleConnectionDataSource.getConnection(SingleConnectionDataSource.java:164) ~[spring-jdbc-5.3.26.jar!/:5.3.26]
		<<snip>>
        at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.26.jar!/:5.3.26]
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.26.jar!/:5.3.26]
		<<snip>>
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.26.jar!/:5.3.26]
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.26.jar!/:5.3.26]
        ... 27 more
  1. What did you expect to see?
    The program should startup and initialize the Snowflake connection.

  2. Can you set logging to DEBUG and collect the logs?
    n/a - unable to even establish a Snowflake connection

  3. What is your Snowflake account identifier, if any? (Optional)
    n/a

@futureviperowner This should have been fixed by #1390
You mentioned the exception is thrown when moving from v3.13.30 of the driver to v3.13.32, but you are currently using v3.13.31? Is it also an issue moving from v3.13.30 to v3.13.31?

Sorry for the confusion. I realized after submitting the issue that I listed the wrong version. I updated the title but forgot to update the actual details. We had updated from v3.13.30 directly to v3.13.32. I just tested all 3 versions:

v3.13.30:
No error.

v3.13.31:

Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 4: file:\C:\dev\<snip>\build\libs\<snip>-application.jar!\BOOT-INF\lib\snowflake-jdbc-3.13.31.jar!\sf_client_config.json
        at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77) ~[?:?]
        at sun.nio.fs.WindowsPath.parse(WindowsPath.java:92) ~[?:?]
        at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232) ~[?:?]
        at java.nio.file.Path.of(Path.java:147) ~[?:?]
        at java.nio.file.Paths.get(Paths.java:69) ~[?:?]
        at net.snowflake.client.config.SFClientConfigParser.loadSFClientConfig(SFClientConfigParser.java:44) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.setClientConfig(DefaultSFConnectionHandler.java:128) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initialize(DefaultSFConnectionHandler.java:109) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initializeConnection(DefaultSFConnectionHandler.java:85) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.initConnectionWithImpl(SnowflakeConnectionV1.java:116) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.<init>(SnowflakeConnectionV1.java:96) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]
        at net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:180) ~[snowflake-jdbc-3.13.31.jar!/:3.13.31]

v3.13.32:

Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 4: file:\C:\dev\<snip>\build\libs\<snip>-application.jar!\BOOT-INF\lib\snowflake-jdbc-3.13.32.jar!\sf_client_config.json
        at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153) ~[?:?]
        at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77) ~[?:?]
        at sun.nio.fs.WindowsPath.parse(WindowsPath.java:92) ~[?:?]
        at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232) ~[?:?]
        at java.nio.file.Path.of(Path.java:147) ~[?:?]
        at java.nio.file.Paths.get(Paths.java:69) ~[?:?]
        at net.snowflake.client.config.SFClientConfigParser.loadSFClientConfig(SFClientConfigParser.java:44) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.setClientConfig(DefaultSFConnectionHandler.java:128) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initialize(DefaultSFConnectionHandler.java:109) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initializeConnection(DefaultSFConnectionHandler.java:85) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.initConnectionWithImpl(SnowflakeConnectionV1.java:116) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.<init>(SnowflakeConnectionV1.java:96) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]
        at net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:180) ~[snowflake-jdbc-3.13.32.jar!/:3.13.32]

I'm not sure about the fix in the linked PR. Java treats backslashes and forward slashes the same when parsing Windows paths. This can be seen in the errors as the path in the error is the same in .31 and .32 since Java normalized the slashes. But a couple of things stand out to me:

  1. The path retrieved by getConfigFilePathFromJDBCJarLocation has file:/ in front of the absolute path. This is not valid. The original bug report in #1390 also has a / preceding the path. When specifying absolute paths containing a drive letter, nothing can go in front of the drive letter.
  2. Even once that's fixed, this comment states that the intent is to strip off the JAR filename. However, the path passed in has a trailing / after the filename and the parsing is done by stripping everything from the last / to the end of the string. So it's not going to strip off the JAR filename.

image

Thanks for the additional testing @futureviperowner. We're checking it internally.

@futureviperowner it looks like a regression as part of a feature that was added to try and help simplify configuring logging.
Can you try as a workaround to export the environment variable SF_CLIENT_CONFIG_FILE pointing it to a valid Windows path instead and a file called sf_client_config.json then add the following content to the file:

{"common":{"log_level":"error","log_path":"<SOME_PATH>/jdbc.log"}}

@sfc-gh-wfateem, thanks for the workaround. I can confirm that this avoids the problem.

Closing since a workaround has been provided. We're following internally for a full fix on the long term.

Fixed via PR1478