Skip to content

fix: catch LinkageError during provider loading#1752

Merged
gnodet merged 1 commit into
masterfrom
ci-issue-1751
Mar 31, 2026
Merged

fix: catch LinkageError during provider loading#1752
gnodet merged 1 commit into
masterfrom
ci-issue-1751

Conversation

@gnodet
Copy link
Copy Markdown
Member

@gnodet gnodet commented Mar 31, 2026

Fixes #1751

Problem

When using the jline bundle jar on JDK 21, loading the FFM terminal provider fails with:

java.lang.UnsupportedClassVersionError: org/jline/terminal/impl/ffm/FfmTerminalProvider
has been compiled by a more recent version of the Java Runtime (class file version 66.0),
this version of the Java Runtime only recognizes class file versions up to 65.0

The FFM provider is compiled for Java 22+ (class file version 66.0). When TerminalProvider.load() attempts to load it on an older JDK, ClassLoader.loadClass() throws UnsupportedClassVersionError, which is a LinkageError (an Error, not an Exception). The catch clause only caught Exception, so the error escaped rather than being wrapped in an IOException for graceful fallback.

Fix

Change catch (Exception e) to catch (Exception | LinkageError e) in TerminalProvider.load(). This catches class-loading errors like UnsupportedClassVersionError and NoClassDefFoundError, wrapping them in IOException so the fallback logic in TerminalBuilder.checkProvider() can handle them gracefully.

Workaround

Users on JDK < 22 can avoid the issue by using the individual small jars instead of the jline bundle jar, and simply not including the jline-terminal-ffm dependency:

<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline-terminal</artifactId>
    <version>4.0.9</version>
</dependency>
<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline-terminal-jni</artifactId>
    <version>4.0.9</version>
</dependency>
<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline-reader</artifactId>
    <version>4.0.9</version>
</dependency>
<!-- Add other modules as needed, but NOT jline-terminal-ffm -->

Alternatively, use the jdk11 classifier of the bundle jar which excludes FFM classes:

<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline</artifactId>
    <version>4.0.9</version>
    <classifier>jdk11</classifier>
</dependency>

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for terminal provider initialization to catch additional error conditions and provide consistent error messages.

When running on JDK 21, loading the FFM terminal provider (compiled for
Java 22) throws UnsupportedClassVersionError, which is a LinkageError
(an Error, not an Exception). The catch clause only caught Exception,
letting the error escape. Catch LinkageError as well so provider loading
failures are properly wrapped in IOException and handled gracefully by
the fallback logic.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 53914065-e780-4ab8-a76f-25634b914481

📥 Commits

Reviewing files that changed from the base of the PR and between b4b2793 and 7f9937d.

📒 Files selected for processing (1)
  • terminal/src/main/java/org/jline/terminal/spi/TerminalProvider.java

📝 Walkthrough

Walkthrough

The TerminalProvider.load() method's exception handling was expanded to catch LinkageError alongside Exception during dynamic provider instantiation. Both error types are now wrapped as IOException with consistent error messaging while preserving the original cause.

Changes

Cohort / File(s) Summary
Error Handling Enhancement
terminal/src/main/java/org/jline/terminal/spi/TerminalProvider.java
Broadened exception catching in provider loader to include LinkageError (e.g., UnsupportedClassVersionError) in addition to Exception, with uniform wrapping as IOException.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A tiny tweak, but oh so keen,
Catching errors that hide between,
LinkageErrors now caught with care,
FfmTerminal works everywhere!
Version clashes fade away,
Harmony reigns, hooray, hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: catching LinkageError exceptions during terminal provider loading.
Linked Issues check ✅ Passed The code change directly addresses issue #1751 by catching LinkageError during provider loading, enabling graceful fallback instead of propagating the UnsupportedClassVersionError.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the LinkageError handling in TerminalProvider.load(), with no unrelated modifications to the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci-issue-1751

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@gnodet gnodet merged commit a13f427 into master Mar 31, 2026
11 checks passed
@gnodet gnodet deleted the ci-issue-1751 branch March 31, 2026 12:02
@gnodet gnodet added the bug label Mar 31, 2026
gnodet added a commit that referenced this pull request Apr 1, 2026
When running on JDK 21, loading the FFM terminal provider (compiled for
Java 22) throws UnsupportedClassVersionError, which is a LinkageError
(an Error, not an Exception). The catch clause only caught Exception,
letting the error escape. Catch LinkageError as well so provider loading
failures are properly wrapped in IOException and handled gracefully by
the fallback logic.
gnodet added a commit that referenced this pull request Apr 27, 2026
When running on JDK 21, loading the FFM terminal provider (compiled for
Java 22) throws UnsupportedClassVersionError, which is a LinkageError
(an Error, not an Exception). The catch clause only caught Exception,
letting the error escape. Catch LinkageError as well so provider loading
failures are properly wrapped in IOException and handled gracefully by
the fallback logic.
gnodet added a commit that referenced this pull request Apr 27, 2026
When running on JDK 21, loading the FFM terminal provider (compiled for
Java 22) throws UnsupportedClassVersionError, which is a LinkageError
(an Error, not an Exception). The catch clause only caught Exception,
letting the error escape. Catch LinkageError as well so provider loading
failures are properly wrapped in IOException and handled gracefully by
the fallback logic.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

java.lang.UnsupportedClassVersionError..class file version 65 66

1 participant