apache/beam · error · IllegalArgumentException

Text payload is not valid UTF-8.

Error message

Text payload is not valid UTF-8.

What it means

Solace.decodeUtf8 throws this IllegalArgumentException when the record's payload bytes cannot be decoded as UTF-8 (the UTF-8 decoder is configured with CodingErrorAction.REPORT). It guards getText(): a record claiming PayloadType.TEXT must contain valid UTF-8, otherwise the bytes are malformed or corrupted.

Solutions

  1. Fix the producing side to encode text as UTF-8 before sending to Solace.
  2. If payloads are genuinely non-UTF-8, send them as BINARY payload type and decode with the correct charset on the consumer side.
  3. On the consumer, catch IllegalArgumentException from getText() and fall back to raw getPayload() with the proper charset.
  4. Validate sample queue payloads with a hex dump to confirm the actual encoding in use.

Example fix

// before
String text = record.getText(); // throws on non-UTF-8
// after
String text;
try {
  text = record.getText();
} catch (IllegalArgumentException e) {
  text = new String(record.getPayload(), Charset.forName("ISO-8859-1"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

try { StandardCharsets.UTF_8.newDecoder().decode(ByteBuffer.wrap(record.getPayload())); } catch (CharacterCodingException e) { /* not UTF-8: handle as binary or alternate charset */ }

Type guard

boolean isUtf8(byte[] b) {
  try { StandardCharsets.UTF_8.newDecoder().decode(ByteBuffer.wrap(b)); return true; }
  catch (CharacterCodingException e) { return false; }
}

Try / catch

try { text = record.getText(); } catch (IllegalArgumentException e) { text = new String(record.getPayload(), fallbackCharset); }

Prevention

When it happens

Trigger: Calling `getText()` on a TEXT-typed record whose payload bytes are not valid UTF-8 — e.g. a producer sent Latin-1/GBK encoded text, or binary data mislabeled as TEXT.

Common situations: Producers on non-JVM platforms using a legacy charset; messages serialized with a different default encoding; corrupted or truncated messages on the queue; mixed-language pipelines assuming UTF-8 everywhere.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/7f3efd05aeb9c660. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/data/Solace.java:347

      public abstract Builder setReplicationGroupMessageId(
          @Nullable String replicationGroupMessageId);

      public abstract Builder setAttachmentBytes(byte[] attachmentBytes);

      public abstract Record build();
    }

    private static String decodeUtf8(byte[] payload) {
      try {
        return StandardCharsets.UTF_8
            .newDecoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT)
            .decode(ByteBuffer.wrap(payload))
            .toString();
      } catch (CharacterCodingException e) {
        throw new IllegalArgumentException("Text payload is not valid UTF-8.", e);
      }
    }
  }

  /**
   * The result of writing a message to Solace. This will be returned by the {@link
   * org.apache.beam.sdk.io.solace.SolaceIO.Write} connector.
   *
   * <p>This class provides a builder to create instances, but you will probably not need it. The
   * write connector will create and return instances of {@link Solace.PublishResult}.
   *
   * <p>If the message has been published, {@link Solace.PublishResult#getPublished()} will be true.
   * If it is false, it means that the message could not be published, and {@link
   * Solace.PublishResult#getError()} will contain more details about why the message could not be
   * published.
   */
  @AutoValue
  @DefaultSchema(AutoValueSchema.class)

View on GitHub (pinned to 12126d8942)