apache/beam · error · IllegalArgumentException

Unknown JMS provider

Error message

Unknown JMS provider '%s' for INDIVIDUAL_ACKNOWLEDGE. Please specify the code explicitly via Read#withIndividualAcknowledgeModeCode(int).

What it means

When reading JMS messages with the INDIVIDUAL_ACKNOWLEDGE mode, Beam's JmsIO must map the underlying JMS connection factory class to a provider-specific acknowledge mode code (e.g. ActiveMQ=4, Qpid/Artemis=101). If the connection class name is not one of the recognized providers, UnboundedJmsReader throws this IllegalArgumentException. The workaround is to set the provider-specific code yourself via Read#withIndividualAcknowledgeModeCode(int).

Solutions

  1. Call JmsIO.read().withIndividualAcknowledgeModeCode(<code>) with your provider's documented individual-acknowledge mode code.
  2. If using a wrapped/pooled ConnectionFactory, ensure the underlying class name contains the broker package, or set the explicit code regardless.
  3. Check the broker's JMSSessionMode documentation (e.g. ActiveMQ Session.INDIVIDUAL_ACKNOWLEDGE=4) and pass that value.

Example fix

// before
JmsIO.<JmsRecord>read().withConnectionFactory(cf).withAcknowledgeMode(JmsIO.INDIVIDUAL_ACKNOWLEDGE)
// after (e.g. IBM MQ code 4 / provider-specific)
JmsIO.<JmsRecord>read().withConnectionFactory(cf)
  .withAcknowledgeMode(JmsIO.INDIVIDUAL_ACKNOWLEDGE)
  .withIndividualAcknowledgeModeCode(4)
Defensive patterns

Strategy: validation

Validate before calling

String cls = connectionFactory.getClass().getName();
boolean known = cls.contains("org.apache.activemq") || cls.contains("org.apache.qpid.jms") || cls.contains("org.apache.activemq.artemis");
if (!known) {
  // must call .withIndividualAcknowledgeModeCode(code)
}

Prevention

When it happens

Trigger: Creating a JmsIO.read() source with withAcknowledgeMode(JmsIO.INDIVIDUAL_ACKNOWLEDGE) whose connection factory class name (from withConnectionFactory) is not apache-activemq, qpid-jms, or artemis — e.g. IBM MQ, Solace, or a custom ConnectionFactory — and no explicit individualAcknowledgeModeCode was configured.

Common situations: Migrating a pipeline to a different JMS broker; using a wrapper or pooled ConnectionFactory whose class name doesn't contain the broker package; copying a config from an ActiveMQ project to another broker.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/io/jms/src/main/java/org/apache/beam/sdk/io/jms/JmsIO.java:752

    private int getAckModeCode(AcknowledgeMode mode) {
      if (mode == AcknowledgeMode.CLIENT_ACKNOWLEDGE
          || mode == AcknowledgeMode.CLIENT_ACKNOWLEDGE_UNSAFE) {
        return Session.CLIENT_ACKNOWLEDGE;
      } else if (mode == AcknowledgeMode.INDIVIDUAL_ACKNOWLEDGE) {
        Integer configuredCode = source.spec.getIndividualAcknowledgeModeCode();
        if (configuredCode != null) {
          return configuredCode;
        }
        String connectionClassName = this.connection.getClass().getName();
        if (connectionClassName.contains("org.apache.activemq.ActiveMQConnection")) {
          return 4;
        } else if (connectionClassName.contains("org.apache.qpid.jms")) {
          return 101;
        } else if (connectionClassName.contains("org.apache.activemq.artemis")) {
          return 101;
        } else {
          throw new IllegalArgumentException(
              String.format(
                  "Unknown JMS provider '%s' for INDIVIDUAL_ACKNOWLEDGE. "
                      + "Please specify the code explicitly via Read#withIndividualAcknowledgeModeCode(int).",
                  connectionClassName));
        }
      } else {
        throw new IllegalArgumentException(String.format("Unknown AcknowledgeMode: %s", mode));
      }
    }

    @Override
    public boolean start() throws IOException {
      Read<T> spec = source.spec;
      ConnectionFactory connectionFactory = spec.getConnectionFactory();
      try {
        Connection connection;
        if (spec.getUsername() != null) {
          connection = connectionFactory.createConnection(spec.getUsername(), spec.getPassword());

View on GitHub (pinned to 12126d8942)