Description
While using a Kafka topic as a GlobalKTable, the application crashes with a NullPointerException when a processing error occurs.
This happens because ProcessingExceptionHandler is not configured in kstreamplify, and Kafka Streams attempts to invoke it as part of its internal error handling mechanism.
Observed Behavior
When a Schema Registry error occurs during GlobalKTable updates, the application fails with:
SerializationException: Error registering Avro schema
Caused by: RestClientException: Schema not found (40403)
This is followed by a fatal error:
java.lang.NullPointerException:
Cannot invoke "org.apache.kafka.streams.errors.ProcessingExceptionHandler.handle(...)"
because "this.processingExceptionHandler" is null
And eventually:
Fatal user code error in processing error callback
→ Kafka Streams shuts down
Context (GlobalKTable specific)
This issue was encountered when:
- A Kafka topic was directly configured as a GlobalKTable
- The topology uses Avro with Schema Registry
- A schema was missing or not registered
The failure happens inside:
GlobalStreamThread
GlobalStateUpdateTask
KTableSourceProcessor
These execution paths are not covered by TopologyExceptionHandler.catchErrors
Why this happens
- Kafka Streams internally relies on
ProcessingExceptionHandler
- kstreamplify does not configure this handler
- When an exception occurs outside
TopologyExceptionHandler.catchErrors, Kafka tries to call:
processingExceptionHandler.handle(...)
Since it is null, Kafka Streams throws a NullPointerException, masking the original exception.
Important Note
This issue still occurs because TopologyExceptionHandler.catchErrors(...) only wraps user-defined topology logic where explicitly applied, and does not cover exceptions occurring in Kafka Streams internal processing, such as:
- GlobalKTable updates (
GlobalStreamThread)
- State store operations triggered internally (e.g. materialization)
- Internal processing nodes (e.g.
ProcessorNode)
As a result, these exceptions rely on ProcessingExceptionHandler, which is not configured by kstreamplify.
Impact
-
Application crashes instead of handling errors gracefully
-
Original exception (Schema Registry error) is masked
-
No DLQ or recovery mechanism is triggered
-
Particularly affects:
- GlobalKTable
- State store updates
- Schema Registry integration
Workaround
Manually configure a ProcessingExceptionHandler:
@Slf4j
public class DebugProcessingHandler implements ProcessingExceptionHandler {
@Override
public ProcessingHandlerResponse handle(
ErrorHandlerContext context,
Record<?, ?> record,
Exception exception) {
log.error("Processing error", exception);
return ProcessingHandlerResponse.CONTINUE;
}
}
Suggested Improvement
-
Provide a default ProcessingExceptionHandler in kstreamplify
-
Ensure it is applied globally, including GlobalStreamThread
-
Optionally implement:
DlqProcessingExceptionHandler (similar to our deserialization DLQ handler)
-
Clarify documentation:
TopologyExceptionHandler.catchErrors does not cover all processing paths
Expected Behavior
Description
While using a Kafka topic as a GlobalKTable, the application crashes with a
NullPointerExceptionwhen a processing error occurs.This happens because
ProcessingExceptionHandleris not configured in kstreamplify, and Kafka Streams attempts to invoke it as part of its internal error handling mechanism.Observed Behavior
When a Schema Registry error occurs during GlobalKTable updates, the application fails with:
This is followed by a fatal error:
And eventually:
Context (GlobalKTable specific)
This issue was encountered when:
The failure happens inside:
GlobalStreamThreadGlobalStateUpdateTaskKTableSourceProcessorThese execution paths are not covered by
TopologyExceptionHandler.catchErrorsWhy this happens
ProcessingExceptionHandlerTopologyExceptionHandler.catchErrors, Kafka tries to call:Important Note
This issue still occurs because TopologyExceptionHandler.catchErrors(...) only wraps user-defined topology logic where explicitly applied, and does not cover exceptions occurring in Kafka Streams internal processing, such as:
GlobalStreamThread)ProcessorNode)As a result, these exceptions rely on ProcessingExceptionHandler, which is not configured by kstreamplify.
Impact
Application crashes instead of handling errors gracefully
Original exception (Schema Registry error) is masked
No DLQ or recovery mechanism is triggered
Particularly affects:
Workaround
Manually configure a
ProcessingExceptionHandler:Suggested Improvement
Provide a default
ProcessingExceptionHandlerin kstreamplifyEnsure it is applied globally, including
GlobalStreamThreadOptionally implement:
DlqProcessingExceptionHandler(similar to our deserialization DLQ handler)Clarify documentation:
TopologyExceptionHandler.catchErrorsdoes not cover all processing pathsExpected Behavior
Processing errors should not result in
NullPointerExceptionApplication should: