Spring Kafka The class is not in the trusted packages
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
This error comes from Spring Kafka's JSON deserialization safeguards. When a consumer receives JSON that claims to represent a Java type, Spring Kafka refuses to instantiate classes from packages you have not explicitly trusted.
That is a security feature, not a random configuration annoyance. The fix is to align the deserializer, the message type headers, and the allowed package list instead of disabling the check blindly.
Why Spring Kafka Uses Trusted Packages
When you use JsonDeserializer, Spring Kafka can deserialize messages into application classes. That is convenient, but arbitrary deserialization is dangerous. A consumer should not instantiate any class named in incoming metadata.
To reduce that risk, the deserializer keeps a trusted package list. If the incoming type information points to com.example.events.OrderCreated, but com.example.events is not trusted, deserialization fails with the familiar exception.
You will usually see this in one of two setups:
- The producer writes type headers, and the consumer rejects the class package
- The consumer expects a default target type, but the configured package list does not include that type
A Minimal Working Consumer Configuration
The cleanest setup is to pick a concrete event type and trust only the package that contains it.
If your messages do not carry type headers, VALUE_DEFAULT_TYPE tells Spring what to create. If they do carry type headers, the trusted package still has to allow that class name.
Spring Boot Property-Based Configuration
If you prefer Boot properties, the same idea can be expressed in application.yml:
This is often enough for a single-event consumer. It also keeps the security boundary visible in configuration rather than burying it inside code.
When Type Headers Are Involved
Many producer setups include a type header such as __TypeId__. The consumer then tries to resolve that fully qualified class name. If the producer sends a class from com.producer.events but your application class lives in com.example.events, you can hit the trusted-package error or a class-resolution mismatch.
In those cases you have three main options:
- Use the same event class package on both sides
- Set an explicit default target type and stop relying on producer type headers
- Use type mappings so header values map to your local classes
The important point is that producer and consumer have to agree on the contract. Kafka transports bytes; Java package names are part of your application protocol only if you choose to make them so.
Why * Is Usually the Wrong Fix
A lot of examples on the internet suggest JsonDeserializer.TRUSTED_PACKAGES = "*". That removes the immediate error, but it also removes the safety boundary. It is acceptable for a quick local experiment, but it is a poor default for production systems.
A tighter package list has two benefits:
- It reduces exposure to unsafe deserialization paths
- It makes message contracts explicit, which helps when teams rename or move event classes
If you need to trust multiple event packages, list them explicitly instead of trusting everything.
Handling Bad Messages Without Crashing the Consumer
A trusted-package error is often a sign that a message contract changed. In production, you usually want to route that record to an error handler or dead-letter topic instead of letting the listener fail in a loop.
That is where ErrorHandlingDeserializer and listener error handlers help. They do not replace trusted packages; they complement them by making failures observable and recoverable.
Common Pitfalls
The first trap is trusting the consumer package instead of the package named in the incoming type header. The deserializer checks the class being created, not the package of your listener.
The second trap is relying on default behavior while the producer writes type headers you forgot about. A hidden header can override your expectations.
Another common issue is moving event classes during refactoring. The application still compiles, but older messages reference the old package name.
Finally, using * to make the error disappear trades a short-term convenience for a security and maintenance problem. Prefer explicit packages or explicit target types.
Summary
- The error means Spring Kafka refused to deserialize a class from an untrusted package.
- '
JsonDeserializer.TRUSTED_PACKAGESmust include the package of the target event class.' - '
VALUE_DEFAULT_TYPEis useful when you want a fixed event type and no header-based guessing.' - Producer type headers and consumer type expectations must agree.
- Trusting
*is easy, but explicit trusted packages are the safer design.

