IDE hook crashes Maven 4

Open
#2,584 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
java

Research direction

Start in plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java at the referenced lines, then reproduce with Maven 4 using the mvn spotless:apply command and the supplied minimal mojo that closes stdout and stderr. Determine whether the IDE hook still needs those streams closed; done means the Maven 4 invocation completes without the cleanup crash while the IDE hook continues to work.

Written by the indexing model from the issue text.

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:

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)

Dominant language
Java
Stars
5.7k
Forks
560
Avg merge
1d 13h
Merged PRs (30d)
43

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from diffplug/spotless

All issues in diffplug/spotless

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.