Skip to content

Fix #11885: Disable ANSI colors when stdout is piped on JDK 22+#11887

Draft
gnodet wants to merge 1 commit intomasterfrom
ci-issue-11885
Draft

Fix #11885: Disable ANSI colors when stdout is piped on JDK 22+#11887
gnodet wants to merge 1 commit intomasterfrom
ci-issue-11885

Conversation

@gnodet
Copy link
Copy Markdown
Contributor

@gnodet gnodet commented Apr 3, 2026

Summary

  • Change ForcedSysOut to SysOut in JLine's TerminalBuilder configuration so that JLine properly checks whether stdout is a TTY before creating a system terminal
  • ForcedSysOut bypasses TTY detection, causing a non-dumb terminal to be created even when stdout is piped (because stdin is still a TTY), resulting in ANSI escape codes in piped output on JDK 22+ where the FFM provider creates a terminal from stdin alone

Root Cause

JLine's SystemOutput.ForcedSysOut always returns SystemStream.Output in select() without checking if stdout is actually a TTY. On JDK 21, the exec/JNI providers would fail to create a system terminal when stdout was piped, falling back to dumb. On JDK 22+ with the FFM provider, the terminal is created successfully (stdin is a TTY), producing a non-dumb terminal with colors enabled even when piped.

SystemOutput.SysOut does the right thing: it checks if stdout is a TTY first. If not, systemStream is null, and JLine falls back to a dumb terminal — exactly the correct behavior.

Test plan

  • mvn help:help -X | less should show plain text (no ANSI codes) on JDK 25+
  • mvn help:help -X > /tmp/out.txt should produce plain text on JDK 25+
  • mvn help:help -X should still show colored output on a real terminal
  • mvn --color=always help:help -X | less should still show ANSI codes (forced)
  • mvn --color=never help:help -X should show plain text
  • Behavior unchanged on JDK 17/21

Fixes #11885

Claude Code on behalf of Guillaume Nodet

🤖 Generated with Claude Code

… JDK 22+

Change ForcedSysOut to SysOut so that JLine properly checks whether
stdout is a TTY before creating a system terminal. ForcedSysOut
bypasses this check, which causes JLine to create a non-dumb terminal
even when stdout is piped (since stdin is still a TTY), resulting in
ANSI escape codes appearing in piped output on JDK 22+ where the FFM
provider successfully creates a terminal from stdin alone.

With SysOut, JLine detects that stdout is not a TTY and falls back to
a dumb terminal, correctly disabling ANSI colors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet added this to the 4.0.0-rc-6 milestone Apr 3, 2026
@gnodet gnodet marked this pull request as draft April 3, 2026 20:32
Copy link
Copy Markdown
Member

@slawekjaranowski slawekjaranowski left a comment

Choose a reason for hiding this comment

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

Test plan pass locally

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.

ANSI colors are not disabled in case of redirect to pipe or file on JDK25+

2 participants