flowable/flowable-engine · error · FlowableException
failed to send event
Error message
failed to send event
What it means
When the Kafka producer future completes exceptionally with an ExecutionException whose cause is not a RuntimeException, the adapter wraps that cause in FlowableException("failed to send event"). This is the generic path for broker-side or serialization failures during a synchronous outbound event send.
Solutions
- Inspect e.getCause() (attached to this FlowableException) for the real Kafka failure.
- Verify broker connectivity, bootstrap servers and topic existence.
- Check Kafka client security config (SASL/SSL) and max.request.size.
- Wrap or retry sends with a dead-letter policy for persistent failures.
Example fix
null
Defensive patterns
Strategy: retry
Validate before calling
// pre-check broker connectivity
try (AdminClient admin = AdminClient.create(Map.of("bootstrap.servers", servers))) {
admin.describeCluster().nodes().get(5, TimeUnit.SECONDS);
} Try / catch
try {
outboundEventBus.send(event);
} catch (FlowableException e) {
if ("failed to send event".equals(e.getMessage()) && isTransient(e.getCause())) {
retryWithBackoff(event);
} else { deadLetter(event, e.getCause()); }
} Prevention
- Always log/inspect getCause() — the real Kafka failure is wrapped
- Set sane delivery.timeout.ms/retries in producer config
- Monitor broker availability and implement dead-letter handling for sends
When it happens
Trigger: kafkaOperations.send(...).get() throws ExecutionException caused by a checked/non-Runtime Throwable, e.g. TimeoutException, authentication/authorization errors (SaslAuthenticationException, TopicAuthorizationException), or serialization errors surfaced as non-Runtime exceptions.
Common situations: Kafka broker down or unreachable (timeout), wrong SASL credentials, topic missing with auto-create disabled, oversized message exceeding max.request.size.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- At least one of topics, topicPartitions or topicPattern…
- Channel definition cannot resolve as a String[] or a String
- Channel model in tenant has retry configuration but no…
- Could not resolve the KafkaListenerContainerFactory to use…
- Endpoint registry does not have listenerContainers field
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b923df032804fbb1.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/KafkaOperationsOutboundEventChannelAdapter.java:78
if (headerValue != null) {
headers.add(new RecordHeader(headerKey, headerValue.toString().getBytes(StandardCharsets.UTF_8)));
}
}
Integer partition = partitionProvider == null ? null : partitionProvider.determinePartition(event);
Object key = messageKeyProvider == null ? null : messageKeyProvider.determineMessageKey(event);
ProducerRecord<Object, Object> producerRecord = new ProducerRecord<>(topic, partition, key, rawEvent, headers);
kafkaOperations.send(producerRecord).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FlowableException("Sending the event was interrupted", e);
} catch (ExecutionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
} else {
throw new FlowableException("failed to send event", e.getCause());
}
}
}
@Override
public void sendEvent(Object rawEvent, Map<String, Object> headerMap) {
throw new UnsupportedOperationException("Outbound processor should never call this");
}
}
View on GitHub (pinned to d6d39ce1c6)