SonarSource/sonarqube · error · IllegalStateException

Error while writing protobuf message

Error message

Error while writing protobuf message

What it means

WsUtils.writeProtobuf serializes a protobuf Message either as binary protobuf or as JSON (via ProtobufJsonFormat + JsonWriter) into the HTTP response. Any exception thrown during that serialization is wrapped in an IllegalStateException with this message, since response serialization failures indicate an internal bug rather than a client error.

Source

Thrown at server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsUtils.java:50

import static org.sonarqube.ws.MediaTypes.JSON;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;

public interface WsUtils {

  static void writeProtobuf(Message msg, Request request, Response response) {
    OutputStream output = response.stream().output();
    try {
      if (request.getMediaType().equals(PROTOBUF)) {
        response.stream().setMediaType(PROTOBUF);
        msg.writeTo(output);
      } else {
        response.stream().setMediaType(JSON);
        try (JsonWriter writer = JsonWriter.of(new OutputStreamWriter(output, UTF_8))) {
          ProtobufJsonFormat.write(msg, writer);
        }
      }
    } catch (Exception e) {
      throw new IllegalStateException("Error while writing protobuf message", e);
    } finally {
      IOUtils.closeQuietly(output);
    }
  }

  static String createHtmlExternalLink(String url, String text) {
    return String.format("<a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">%s</a>", url, text);
  }
}

View on GitHub (pinned to 184c821202)

Solutions

  1. Inspect the wrapped cause (e.getCause()) to identify whether it is an IO problem or a protobuf serialization problem
  2. If the cause is a broken pipe/IO error, it is a client disconnect and can be ignored or logged at debug
  3. If the cause is ProtobufFormat/serialization, fix the message construction in the WS handler (e.g. invalid enum or bytes field)

Example fix

// before
ProtobufFormat.write(msg, output); // raw bytes when client expects JSON
// after
response.stream().setMediaType(JSON);
try (JsonWriter writer = JsonWriter.of(new OutputStreamWriter(output, UTF_8))) {
  ProtobufJsonFormat.write(msg, writer);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!msg.isInitialized()) throw new Error('Protobuf message not initialized before write');

Type guard

const isWritableMessage = (m) => m && typeof m.isInitialized === 'function' && m.isInitialized();

Try / catch

try { writeProtobuf(msg, request, response); } catch (IllegalStateException e) { if (e.getCause() instanceof IOException) { log.debug('Client aborted', e); } else { throw e; } }

Prevention

When it happens

Trigger: Writing a web service response whose protobuf message fails ProtobufJsonFormat.write() (e.g. invalid UTF-8 or unserializable field state) or when the underlying OutputStream/JsonWriter throws (client disconnected, broken pipe, IO error).

Common situations: Client aborting the connection mid-response causing a broken pipe; a protobuf field holding invalid state (e.g. bytes that violate the JSON format); custom plugin web services emitting malformed protobufs.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/d10437ffcd5dcf0d. Report an issue: GitHub.