Skip to content

Crash the SDK on startup if mixed versions have been detected #4277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Mar 27, 2025

Conversation

adinauer
Copy link
Member

@adinauer adinauer commented Mar 21, 2025

📜 Description

We check the versions of loaded Sentry dependencies. If there is a mismatch between them we now throw an exception on Sentry.init / SentryAndroid.init. If we do not throw early the application may crash soon thereafter or at some random point depending on features used and versions mixed. We opt for the controlled exception here vs. having crashes that are hard to understand later.

NOTE:
This detection at startup will only work for new releases, so mixing 8.6.0 (assuming this PR lands there) and 8.1.0 will not be detected at startup as the MANIFEST.MF files with version are only present in new releases. For Android registering the packages and their version in static blocks is also new.

💡 Motivation and Context

Fixes #4132

💚 How did you test it?

📝 Checklist

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

Here's a sample exception when starting up Spring Boot 3:

org.springframework.context.ApplicationContextException: Unable to start web server
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621) ~[spring-context-6.2.2.jar:6.2.2]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.2.jar:3.4.2]
	at io.sentry.samples.spring.boot.jakarta.SentryDemoApplication.main(SentryDemoApplication.java:27) ~[main/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:147) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:107) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:516) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:222) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:188) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-3.4.2.jar:3.4.2]
	... 8 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sentryUserFilter' defined in class path resource [io/sentry/spring/boot/jakarta/SentryAutoConfiguration$HubConfiguration$SentryWebMvcConfiguration.class]: Unsatisfied dependency expressed through method 'sentryUserFilter' parameter 0: Error creating bean with name 'sentryHub' defined in class path resource [io/sentry/spring/boot/jakarta/SentryAutoConfiguration$HubConfiguration.class]: Failed to instantiate [io.sentry.IScopes]: Factory method 'sentryHub' threw exception with message: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/java/troubleshooting/mixed-versions for more details.
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1361) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:307) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:211) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:202) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addServletContextInitializerBeans(ServletContextInitializerBeans.java:97) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:86) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:266) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:240) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:52) ~[spring-boot-3.4.2.jar:3.4.2]
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4426) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1203) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1193) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) ~[na:na]
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:749) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:772) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1203) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1193) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) ~[na:na]
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:749) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:203) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:415) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:870) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.apache.catalina.startup.Tomcat.start(Tomcat.java:437) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:128) ~[spring-boot-3.4.2.jar:3.4.2]
	... 13 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sentryHub' defined in class path resource [io/sentry/spring/boot/jakarta/SentryAutoConfiguration$HubConfiguration.class]: Failed to instantiate [io.sentry.IScopes]: Factory method 'sentryHub' threw exception with message: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/java/troubleshooting/mixed-versions for more details.
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:657) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:645) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1361) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:307) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1631) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1519) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:913) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-6.2.2.jar:6.2.2]
	... 53 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.sentry.IScopes]: Factory method 'sentryHub' threw exception with message: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/java/troubleshooting/mixed-versions for more details.
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:199) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:88) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:168) ~[spring-beans-6.2.2.jar:6.2.2]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-6.2.2.jar:6.2.2]
	... 67 common frames omitted
Caused by: java.lang.IllegalStateException: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/java/troubleshooting/mixed-versions for more details.
	at io.sentry.util.InitUtil.shouldInit(InitUtil.java:30) ~[sentry-8.4.0-SNAPSHOT.jar:8.4.0-SNAPSHOT]
	at io.sentry.Sentry.init(Sentry.java:296) ~[sentry-8.4.0-SNAPSHOT.jar:8.4.0-SNAPSHOT]
	at io.sentry.Sentry.init(Sentry.java:261) ~[sentry-8.4.0-SNAPSHOT.jar:8.4.0-SNAPSHOT]
	at io.sentry.spring.boot.jakarta.SentryAutoConfiguration$HubConfiguration.sentryHub(SentryAutoConfiguration.java:176) ~[sentry-spring-boot-jakarta-8.3.0.jar:8.3.0]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:171) ~[spring-beans-6.2.2.jar:6.2.2]
	... 70 common frames omitted

Here's a sample crash for Android:

FATAL EXCEPTION: main
                                                                                                    Process: io.sentry.samples.android, PID: 8881
                                                                                                    java.lang.RuntimeException: Unable to get provider io.sentry.android.core.SentryInitProvider: java.lang.IllegalStateException: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/android/troubleshooting/mixed-versions for more details.
                                                                                                    	at android.app.ActivityThread.installProvider(ActivityThread.java:7427)
                                                                                                    	at android.app.ActivityThread.installContentProviders(ActivityThread.java:6939)
                                                                                                    	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6710)
                                                                                                    	at android.app.ActivityThread.access$1500(ActivityThread.java:247)
                                                                                                    	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                    	at android.os.Looper.loop(Looper.java:288)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7839)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
                                                                                                    Caused by: java.lang.IllegalStateException: Sentry SDK has detected a mix of versions. This is not supported and likely leads to crashes. Please always use the same version of all Java SDK modules (dependencies). See https://docs.sentry.io/platforms/android/troubleshooting/mixed-versions for more details.
                                                                                                    	at io.sentry.util.InitUtil.shouldInit(InitUtil.java:30)
                                                                                                    	at io.sentry.Sentry.init(Sentry.java:296)
                                                                                                    	at io.sentry.Sentry.init(Sentry.java:217)
                                                                                                    	at io.sentry.android.core.SentryAndroid.init(SentryAndroid.java:97)
                                                                                                    	at io.sentry.android.core.SentryAndroid.init(SentryAndroid.java:69)
                                                                                                    	at io.sentry.android.core.SentryInitProvider.onCreate(SentryInitProvider.java:25)
                                                                                                    	at android.content.ContentProvider.attachInfo(ContentProvider.java:2404)
                                                                                                    	at android.content.ContentProvider.attachInfo(ContentProvider.java:2374)
                                                                                                    	at io.sentry.android.core.SentryInitProvider.attachInfo(SentryInitProvider.java:43)
                                                                                                    	at android.app.ActivityThread.installProvider(ActivityThread.java:7422)
                                                                                                    	at android.app.ActivityThread.installContentProviders(ActivityThread.java:6939) 
                                                                                                    	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6710) 
                                                                                                    	at android.app.ActivityThread.access$1500(ActivityThread.java:247) 
                                                                                                    	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053) 
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:106) 
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:201) 
                                                                                                    	at android.os.Looper.loop(Looper.java:288) 
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7839) 
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method) 
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 

To test this you may need to change the version in gradle.properties to a SNAPSHOT use ./gradlew publishToMavenLocal -x test, then revert gradle.properties and use both the version with and without SNAPSHOT to cause the mixed version detection to kick in.

Copy link
Contributor

github-actions bot commented Mar 21, 2025

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 9cb40c2

@adinauer
Copy link
Member Author

Need to create the linked docs page and explain common causes and how to fix this.

Copy link
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry/src/main/java/io/sentry/transport/RateLimiter.java

Copy link
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry/src/main/java/io/sentry/transport/RateLimiter.java

Copy link
Contributor

github-actions bot commented Mar 24, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 400.51 ms 500.46 ms 99.95 ms
Size 1.58 MiB 2.22 MiB 654.87 KiB

Previous results on branch: feat/crash-on-startup-with-mixed-versions

Startup times

Revision Plain With Sentry Diff
aba15a8 405.40 ms 427.65 ms 22.25 ms
a3e6b58 412.50 ms 417.29 ms 4.79 ms

App size

Revision Plain With Sentry Diff
aba15a8 1.58 MiB 2.22 MiB 654.92 KiB
a3e6b58 1.58 MiB 2.22 MiB 654.87 KiB

Copy link
Member

@lcian lcian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Platform.isAndroid()
? "https://docs.sentry.io/platforms/android/troubleshooting/mixed-versions"
: "https://docs.sentry.io/platforms/java/troubleshooting/mixed-versions";
throw new IllegalStateException(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope people won't put a try-catch around this 😄

Base automatically changed from feat/manifest-for-jars to main March 27, 2025 11:47
@adinauer adinauer merged commit bfbc9e1 into main Mar 27, 2025
34 of 35 checks passed
@adinauer adinauer deleted the feat/crash-on-startup-with-mixed-versions branch March 27, 2025 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Detect a mismatch in dependency versions
4 participants