Hi Solace Community,
After upgrading a Spring Cloud Stream consumer (Solace binder), the consumer fails before my handler runs with a header deserialization error like:
Failed to deserialize object / InvalidClassException (serialVersionUID mismatch)
Stack trace indicates it happens during inbound header mapping (e.g., XMLMessageMapper.mapHeadersToSpring() → SerializationUtils.deserialize()), likely because a producer is sending a Java-serialized object in message headers.
Is there a recommended way (consumer-side) to:
disable Java deserialization of inbound headers / treat them as raw bytes or strings, or
sync the serialization, or
exclude/blacklist certain headers from being mapped?
I have a lot of pipelines that needs to be migrated to newer versions, I wanted to migrate one pipeline at a time. Would it be possible to sync older producer with new consumer, and what should be the way?
Hi there, I’m Solly AI, I generate responses to your questions using the power of the Solace Agent Mesh:
Please remember that AI technology can make mistakes so ensure that you read our Disclaimer.
AI Generated responses are a work in progress, your help in evaluating my response would be awesome! If my response makes sense, please mark it as a solution or give a . If my response doesn’t make sense for your topic, please react to it with a .
I don’t have the information on that.
The provided facts cover related Spring Cloud Stream and Solace binder topics (such as payload deserialization, Spring library upgrade issues, and error handling), but none of them directly address the specific scenarios you’re asking about:
Disabling Java deserialization of inbound headers (treating them as raw bytes/strings) in XMLMessageMapper.mapHeadersToSpring()
Syncing serialization between producer and consumer to resolve InvalidClassException / serialVersionUID mismatches
Excluding/blacklisting specific headers from inbound header mapping
Strategies for migrating pipelines one at a time with mixed producer/consumer versions
For these specific concerns, I’d recommend searching the Solace documentation and the Solace Spring Cloud binder GitHub repository directly, particularly the XMLMessageMapper source and the binder’s consumer configuration properties, which may expose options for header mapping control.
It would have been better, if you could share the stack trace. The consumer side deserialization may be failing if the serialized Class is not on the classpath. If your consumer application depends on the header, it need to solve the deserialization.
I believe Publisher application is Solace Spring Cloud Stream application, as Solace SCSt publisher serializes the headers values of type Java Object (non primitives).
If you have control on the publisher app, the headers that are java objects and being serialized could be excluded from solace message or converted to simple string header.
Please have a look at the Solace Producer Properties, namely headerExclusions , headerTypeCompatibility and nonserializableHeaderConvertToString .
Similarly, on the consumer side you could exclude the problematic property by setting headerExclusionsSolace Consumer Property- if consumer doesn’t need to process the property.
Here is the full stack when consumer is consuming a message:
2026-03-05T19:51:34.441+05:30 ERROR 43320 — [consumer-input1] o.s.integration.handler.LoggingHandler : java.lang.IllegalArgumentException: Failed to deserialize object
at org.springframework.util.SerializationUtils.deserialize(SerializationUtils.java:86)
at com.solace.spring.cloud.stream.binder.util.XMLMessageMapper.mapHeadersToSpring(XMLMessageMapper.java:464)
at com.solace.spring.cloud.stream.binder.util.XMLMessageMapper.mapToSpringInternal(XMLMessageMapper.java:346)
at com.solace.spring.cloud.stream.binder.util.XMLMessageMapper.mapToSpring(XMLMessageMapper.java:285)
at com.solace.spring.cloud.stream.binder.util.XMLMessageMapper.mapToSpring(XMLMessageMapper.java:280)
at com.solace.spring.cloud.stream.binder.inbound.InboundXMLMessageListener.createOneMessage(InboundXMLMessageListener.java:234)
at com.solace.spring.cloud.stream.binder.inbound.InboundXMLMessageListener.lambda$processMessage$1(InboundXMLMessageListener.java:161)
at com.solace.spring.cloud.stream.binder.inbound.BasicInboundXMLMessageListener.handleMessage(BasicInboundXMLMessageListener.java:60)
at com.solace.spring.cloud.stream.binder.inbound.InboundXMLMessageListener.processMessage(InboundXMLMessageListener.java:161)
at com.solace.spring.cloud.stream.binder.inbound.InboundXMLMessageListener.receive(InboundXMLMessageListener.java:147)
at com.solace.spring.cloud.stream.binder.inbound.InboundXMLMessageListener.run(InboundXMLMessageListener.java:96)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:317)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
at — Async.Stack.Trace — (captured by IntelliJ IDEA debugger)
at java.base/java.util.concurrent.FutureTask.(FutureTask.java:151)
at java.base/java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:98)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:122)
at com.solace.spring.cloud.stream.binder.inbound.JCSMPInboundChannelAdapter.lambda$doStart$0(JCSMPInboundChannelAdapter.java:205)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at com.solace.spring.cloud.stream.binder.inbound.JCSMPInboundChannelAdapter.doStart(JCSMPInboundChannelAdapter.java:203)
at org.springframework.integration.endpoint.AbstractEndpoint.start(AbstractEndpoint.java:152)
at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder.doBindConsumer(AbstractMessageChannelBinder.java:549)
at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder.doBindConsumer(AbstractMessageChannelBinder.java:103)
at org.springframework.cloud.stream.binder.AbstractBinder.bindConsumer(AbstractBinder.java:144)
at org.springframework.cloud.stream.binding.BindingService.doBindConsumer(BindingService.java:188)
at org.springframework.cloud.stream.binding.BindingService.bindConsumer(BindingService.java:141)
at org.springframework.cloud.stream.binding.AbstractBindableProxyFactory.createAndBindInputs(AbstractBindableProxyFactory.java:99)
at org.springframework.cloud.stream.binding.InputBindingLifecycle.doStartWithBindable(InputBindingLifecycle.java:59)
at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:833)
at org.springframework.cloud.stream.binding.AbstractBindingLifecycle.start(AbstractBindingLifecycle.java:60)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:405)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:394)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:586)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:364)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:310)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:1010)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:631)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350)
at org.example.Main.main(Main.java:11)
Caused by: java.io.InvalidClassException: org.springframework.util.MultiValueMapAdapter; local class incompatible: stream classdesc serialVersionUID = -1297985047093119690, local class serialVersionUID = 1458406687712361249
at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:598)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2078)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1927)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2078)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1927)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2252)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1762)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:540)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:498)
at org.springframework.util.SerializationUtils.deserialize(SerializationUtils.java:83)
… 52 more
2026-03-05T19:51:34.447+05:30 INFO 43320 — [consumer-input1] c.s.s.c.s.b.u.SolaceErrorMessageHandler : Processing message 1d888d1d-30c4-8700-d03b-d6a5379c6a60 <messaging-exception-message: null, original-message: null, source-jcsmp-message: 1>
2026-03-05T19:51:34.448+05:30 INFO 43320 — [consumer-input1] .s.b.u.ErrorQueueRepublishCorrelationKey : Republishing XMLMessage 1 to error queue scst/error/wk/exclusive/plain/RRCP_HKMA_DECOMPOSITION_LOCAL_TRADE_TEST - attempt 1 of 3
When Java serializes an object, it writes the class’s serialVersionUID into the byte stream as a fingerprint. On deserialization, Java checks that the UID in the stream matches the UID of the loaded class.
If they differ, it throws InvalidClassException.
Root Cause in your case
stream classdesc serialVersionUID = -1297985047093119690 ← what was serialized
local class serialVersionUID = 1458406687712361249 ← what’s in your classpath now
The MultiValueMapAdapter class from spring-web was serialized with one version of Spring, but your application is trying to deserialize it with a different Spring version where the serialVersionUID changed.
As you mentioned, issue happend after upgrading spring boot version on consumer side. The serialVersionUID of the class has changed between two versions of spring boot. I think if you upgrade spring boot version in publisher app, issue should be fixed.
Alternatively, have you tried headerExclusions property, I mentioned in my previous reply ?