jEdit 5.7.0 can throw a repeated NullPointerException from TextAreaMouseHandler.doSingleClick() when an ordinary mouse click is processed while the clicked/caret offset is temporarily not represented as a visible point in the text area.
The exception is logged silently in activity.log; no normal error dialog is shown.
The immediate failure is:
java.lang.NullPointerException: Cannot read field "x" because "<local4>" is null
at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.doSingleClick(TextAreaMouseHandler.java:224)
at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.mousePressed(TextAreaMouseHandler.java:132)
at org.gjt.sp.jedit.textarea.MouseHandler.mousePressed(MouseHandler.java:64)
The problem appears to be a missing null check in the core mouse handler.
In the jEdit 5.7.0 source, TextAreaMouseHandler.doSingleClick() does approximately:
Point p = textArea.offsetToXY(dragStart);
textArea.moveCaretPosition(dragStart,
(p.x < 0) ? TextArea.NO_SCROLL : TextArea.NORMAL_SCROLL);
However, the documented contract of TextArea.offsetToXY(...) explicitly allows it to return null when the requested offset is not currently visible.
Therefore p.x can legitimately dereference null.
This is not only a macro-side exception: the uncaught NPE occurs inside jEdit's core mouse-event handler on the AWT Event Dispatch Thread.
jEdit version: 5.7.0
Build: 2025-08-08
Java runtime version: 17.0.20
OS:
ActionHooks 0.6
BufferTabs 1.2.5
CandyFolds 1.2.3
Character Map 1.3.3
Common Controls 1.7.4
Console 5.1.4
Context Menu 0.4
DirtyGutter 0.3b
Editor Scheme 1.8
ErrorList 2.4.0
FTP 1.4
Finish Him! 0.9
FoldViewer 1.1
GnuRegexp 1.0.1
Image Viewer 1.4
Info Viewer 1.6.3
JDiff Plugin 3.4.0
Jakarta Commons 0.9
Menu Editor 0.5
MetalColor 1.1.0
Mouse Snap 0.1
OpenIt 1.6.0
Project Viewer 3.6
QuickNotepad 5.0
RecentBufferSwitcher 0.2
Reopen 0.6
Scala Plugin 1.1.0
TaskList 2.7
Templates 5.1.0
TextTools 1.16
Undo Repair 1.0
WhiteSpace 1.0.3
XSearch 1.9
I currently encounter the problem after a BeanShell text-editing macro performs a multiline edit followed by caret/scroll updates.
A representative sequence is:
PositionChanging is emitted.TextAreaMouseHandler.doSingleClick() throws the NPE shown below.In my specific case, immediately before the failure the activity log contains:
14:48:21 [AWT-EventQueue-0] [message] BeanShell: Running script .../+ [NumPadAdd].bsh
14:48:21 [AWT-EventQueue-0] [debug] EditBus: PositionChanging[what=POSITION_CHANGING,source=org.gjt.sp.jedit.EditPane[active]]
14:48:21 [AWT-EventQueue-0] [notice] String: [METHOD] Function::: ensureCaretVisible; Timestamp::: 20260913144821
14:48:21 [AWT-EventQueue-0] [notice] String: [METHOD] Function::: ensureCaretVisible; Timestamp::: 20260913144821
14:48:22 [AWT-EventQueue-0] [debug] EditBus: PositionChanging[what=POSITION_CHANGING,source=org.gjt.sp.jedit.EditPane[active]]
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: Exception in thread "AWT-EventQueue-0"
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: java.lang.NullPointerException: Cannot read field "x" because "<local4>" is null
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.doSingleClick(TextAreaMouseHandler.java:224)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.mousePressed(TextAreaMouseHandler.java:132)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.MouseHandler.mousePressed(MouseHandler.java:64)
I have not yet reduced the trigger to a plugin-free / stock-jEdit-only GUI sequence.
Nevertheless, the core failure itself does not appear to depend on a plugin API: TextAreaMouseHandler.doSingleClick() dereferences the result of an API method whose documented return value can be null.
A macro or plugin may make this state easier to reach, but it should not be able to cause an uncaught NPE merely by using normal text-area editing/caret APIs.
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: Exception in thread "AWT-EventQueue-0"
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: java.lang.NullPointerException: Cannot read field "x" because "<local4>" is null
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.doSingleClick(TextAreaMouseHandler.java:224)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.TextAreaMouseHandler.mousePressed(TextAreaMouseHandler.java:132)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at org.gjt.sp.jedit.textarea.MouseHandler.mousePressed(MouseHandler.java:64)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:289)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Component.processMouseEvent(Component.java:6623)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Component.processEvent(Component.java:6391)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Container.processEvent(Container.java:2266)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4572)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
14:48:22 [AWT-EventQueue-0] [error] AWT-EventQueue-0: at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
The same exception occurred repeatedly on subsequent mouse presses at approximately 14:48:22–14:48:23.
A normal single click in the text area should move the caret / update selection normally.
If the target offset cannot currently be converted to an on-screen point, the mouse handler should handle that condition without throwing.
No exception should escape onto the AWT Event Dispatch Thread.
TextArea.offsetToXY(dragStart) returns null.
TextAreaMouseHandler.doSingleClick() then unconditionally accesses p.x, causing:
java.lang.NullPointerException: Cannot read field "x" because "<local4>" is null
The mouse event is aborted and the exception is written to activity.log.
Repeated clicks can cause repeated exceptions.
For jEdit 5.7.0, the relevant code is in:
org/gjt/sp/jedit/textarea/TextAreaMouseHandler.java
doSingleClick(MouseEvent evt)
approximately lines 220-225
The logic obtains:
Point p = textArea.offsetToXY(dragStart);
and immediately evaluates p.x.
However, TextArea.offsetToXY(...) documents null as a valid result when the requested offset is not visible.
Therefore doSingleClick() should not assume that the returned Point is non-null.
This also explains the Java 17 NPE message: local variable p is <local4>.
A minimal fix would be to treat p == null like an off-screen result:
Point p = textArea.offsetToXY(dragStart);
int scrollMode = (p == null || p.x < 0)
? TextArea.NO_SCROLL
: TextArea.NORMAL_SCROLL;
textArea.moveCaretPosition(dragStart, scrollMode);
This appears consistent with the existing comment:
defer scrolling until mouserelease if result is off-screen
because null from offsetToXY() means that the requested offset is not currently visible.
Alternatively, if another behavior is preferred when p == null, the important requirement is that the documented null return must be handled before dereferencing p.x.
There appear to be other places in TextAreaMouseHandler that also assume offsetToXY(...) cannot return null, for example direct .x use in the virtual-space calculations and similar logic in doSingleDrag().
It may be worth auditing all offsetToXY(...) calls in this class for the same documented-null condition rather than fixing only line 224.
The stack trace reported here specifically identifies the dereference in doSingleClick() line 224.
There is an older jEdit core issue:
#3517 - NPE when scrolling to top after multiline delete (soft wrap)
That issue involved text-area state after multiline deletion and was fixed in 2012.
It does not appear to be the same bug:
TextArea.scrollTo();TextAreaMouseHandler.doSingleClick();offsetToXY().The older issue may nevertheless be useful historical context because both involve temporary text-area display/cache state after multiline editing.
The trigger was observed in a setup with the plugins listed above, but the actual exception occurs entirely in jEdit core mouse handling.
I have not identified a plugin frame in the exception stack.
The triggering BeanShell macro may expose a timing/display-state condition, but the core handler should still safely handle the documented null return from offsetToXY().
The immediate source-level null dereference should be independently verifiable from the jEdit 5.7.0 source.