alibaba/canal · warning · CanalException

Stop RabbitMQ producer error

Error message

Stop RabbitMQ producer error

What it means

Thrown by CanalRabbitMQProducer.stop when channel.close()/connect.close() raise IOException or TimeoutException during producer shutdown. AlreadyClosedException is caught separately and only logged, so this error specifically means the close failed on a connection/channel that was (at the time) believed open.

Source

Thrown at connector/rabbitmq-connector/src/main/java/com/alibaba/otter/canal/connector/rabbitmq/producer/CanalRabbitMQProducer.java:216

            channel.basicPublish(rabbitMQProperties.getExchange(),
                queueName,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void stop() {
        logger.info("## Stop RabbitMQ producer##");
        try {
            this.channel.close();
            this.connect.close();
        } catch (AlreadyClosedException ex) {
            logger.error("Connection is already closed", ex);
        } catch (IOException | TimeoutException ex) {
            throw new CanalException("Stop RabbitMQ producer error", ex);
        } finally {
            super.stop();
        }
    }
}

View on GitHub (pinned to 87be50e876)

Solutions

  1. Like other shutdown errors, prefer logging over throwing — the producer is stopping anyway.
  2. If you must propagate, ensure callers treat producer-stop failures as non-fatal cleanup noise.
  3. Ensure super.stop() still runs (it is in finally) so connector lifecycle stays consistent even when close fails.

Example fix

// before
} catch (IOException | TimeoutException ex) {
    throw new CanalException("Stop RabbitMQ producer error", ex);
} finally {
    super.stop();
}

// after — best-effort close, always run super.stop()
try {
    this.channel.close();
    this.connect.close();
} catch (AlreadyClosedException ex) {
    logger.error("Connection is already closed", ex);
} catch (IOException | TimeoutException ex) {
    logger.warn("Stop RabbitMQ producer error (best-effort)", ex);
} finally {
    super.stop();
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    this.channel.close();
    this.connect.close();
} catch (AlreadyClosedException ex) {
    logger.error("Connection is already closed", ex);
} catch (IOException | TimeoutException ex) {
    logger.warn("Stop RabbitMQ producer error (best-effort)", ex);
} finally {
    super.stop();
}

Prevention

When it happens

Trigger: this.channel.close() or this.connect.close() at lines 211-212 throw IOException/TimeoutException. Causes: broker/network dropped during shutdown so the close handshake fails or times out; a resource-level error left the channel in a recoverable-but-not-cleanly-closable state.

Common situations: Stopping the producer right as the broker becomes unreachable; slow broker causing close timeout; the auto-recovery client mid-reconnect during stop.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/671e94af0ef019b9. Report an issue: GitHub.