diffplug / diffplug/spotless

IDE hook crashes Maven 4

Open
#2,584 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
5.6k
Forks
559
Avg merge
1d 13h
Merged PRs (30d)
34

Description

I am looking at developing a VSCode plugin for Spotless that works with Maven. For performance reasons I want to use `mvnd` which is a daemon-based version of Maven, and which is based on Maven 4.x.

I have found that on Maven 4, if I invoke:

```
$ mvn spotless:apply -DspotlessIdeHook=/home/jay/Projects/vscode-spotless-maven/test-project/src/main/java/com/mycompany/app/App.java
```

then it executes successfully but crashes Maven while cleaning up:

```
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------------------------< com.mycompany.app:my-app >-----------------------------------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] ---------------------------------------------------------[ jar ]----------------------------------------------------------
[INFO]
[INFO] --- spotless:2.46.1:apply (default-cli) @ my-app ---
[WARNING] [stderr] IS CLEAN
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] Total time: 0.802 s
[INFO] Finished at: 2025-08-02T16:33:13+01:00
[INFO] --------------------------------------------------------------------------------------------------------------------------
[ERROR] Unable to close context
org.apache.maven.api.cli.InvokerException: Unable to close context
at org.apache.maven.cling.invoker.LookupContext.close(LookupContext.java:128)
at org.apache.maven.cling.invoker.LookupInvoker.invoke(LookupInvoker.java:143)
at org.apache.maven.cling.ClingSupport.run(ClingSupport.java:76)
at org.apache.maven.cling.MavenCling.main(MavenCling.java:51)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:255)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:201)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:361)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:314)
Suppressed: java.lang.NullPointerException: Cannot invoke "org.apache.maven.logging.LoggingOutputStream.forceFlush()" because "this.out" is null
at org.apache.maven.logging.LoggingOutputStream$LoggingPrintStream.forceFlush(LoggingOutputStream.java:88)
at org.apache.maven.logging.LoggingOutputStream.forceFlush(LoggingOutputStream.java:94)
at org.apache.maven.cling.invoker.LookupInvoker.lambda$doConfigureWithTerminalWithRawStreamsDisabled$3(LookupInvoker.java:378)
at org.apache.maven.cling.invoker.LookupContext.close(LookupContext.java:118)
... 9 more
Suppressed: java.lang.NullPointerException: Cannot invoke "org.apache.maven.logging.LoggingOutputStream.forceFlush()" because "this.out" is null
at org.apache.maven.logging.LoggingOutputStream$LoggingPrintStream.forceFlush(LoggingOutputStream.java:88)
at org.apache.maven.logging.LoggingOutputStream.forceFlush(LoggingOutputStream.java:94)
at org.apache.maven.cling.invoker.LookupInvoker.lambda$doConfigureWithTerminalWithRawStreamsDisabled$1(LookupInvoker.java:376)
at org.apache.maven.cling.invoker.LookupContext.close(LookupContext.java:118)
... 9 more
```

Note that Spotless doesn't crash Maven if you don't use the IDE hook.

I have been able to narrow this down to the following code in the Maven IDE hook:

https://github.com/diffplug/spotless/blob/7d5c826973a900713fe7b23ed20113b0c2c2315e/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java#L69-L72

I believe this code is the cause because if I make my own minimal mojo on Maven 4.x which looks like this:

```java
package sample.plugin;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;

@Mojo(name = "sayhi")
public class GreetingMojo extends AbstractMojo
{
@Override
public void execute() throws MojoExecutionException
{
getLog().info("Hello, world.");

System.err.close();
System.out.close();
}
}
```

then I am able to reproduce the same crash with `mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi`. If I then comment those two lines of code out, the crash disappears.

I wanted to ask why we need to close stdout/stderr after the IDE hook has finished? It might well be that this is a Maven issue rather than a Spotless issue (it doesn't feel like a plugin should be able to crash the host build system) but if we can do a quick fix here rather than waiting for a change in Maven that would be great.

## Issue template

spotless version: 2.46.1
maven version: Apache Maven 4.0.0-rc-4 (bed0f8174bf728978f86fac533aa38a9511f3872)
repro: https://github.com/SapiensAnatis/vscode-spotless-maven/tree/master/test-project (but any Spotless project will work fine if my understanding of the cause is correct)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.