Skip to content

NPE in HttpChannelState.completeStream() when _request is null during multipart cleanup #14745

@bjorncs

Description

@bjorncs

Jetty version(s)

12.0.33

Jetty Environment

core

HTTP version

HTTP 1.1

Java version/vendor

OpenJDK 17

OS type/version

AlmaLinux 8

Description

HttpChannelState.completeStream() throws a NullPointerException when cleaning up multipart form data if _request has already been nulled by recycle().

The crash occurs at HttpChannelState.java:642:

MultiPartFormData.Parts parts = MultiPartFormData.getParts(_request);

MultiPartFormData.getParts(Attributes) does not guard against a null argument, and _request can be null if recycle() has already run.

Stack trace:

java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.util.Attributes.getAttribute(String)" because "attributes" is null
    at org.eclipse.jetty.http.MultiPartFormData.getParts(MultiPartFormData.java:129)
    at org.eclipse.jetty.server.internal.HttpChannelState.completeStream(HttpChannelState.java:642)
    at org.eclipse.jetty.server.internal.HttpChannelState$LastWriteCallback.completeLastWrite(HttpChannelState.java:800)
    at org.eclipse.jetty.server.internal.HttpChannelState$LastWriteCallback.succeeded(HttpChannelState.java:775)
    at org.eclipse.jetty.util.thread.Invocable$ReadyTask.run(Invocable.java:177)
    at org.eclipse.jetty.util.thread.SerializedInvoker$Link.run(SerializedInvoker.java:268)
    at org.eclipse.jetty.util.thread.SerializedInvoker.run(SerializedInvoker.java:168)
    at org.eclipse.jetty.server.internal.HttpChannelState$ChannelResponse.failed(HttpChannelState.java:1396)
    at org.eclipse.jetty.io.AbstractConnection.lambda$failedCallback$0(AbstractConnection.java:99)

The call path suggests a connection failure (client disconnect) during response writing, where the failure handling races with channel recycling. The AbstractConnection.failedCallback origin indicates the underlying connection failed while the response write was still in progress.

How to reproduce?

We observe this sporadically in production when handling multipart/form-data requests (file uploads) under load with keep-alive connections. We believe it occurs when the client disconnects before the server finishes writing the response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions