apache/beam · error · IllegalArgumentException
SolaceIO.Write: Unknown destination type
Error message
SolaceIO.Write: Unknown destination type: ${destination.getType()} What it means
SolaceIO.Write's convertToJcsmpDestination only maps TOPIC and QUEUE destination types; any other Solace.DestinationType throws this IllegalArgumentException. It is a defensive check that every destination the writer emits is one JCSMP can represent.
Solutions
- Return Solace.DestinationType.TOPIC or QUEUE from your Destination implementation.
- In your custom mapping, build a topic-only Destination: use Solace.DestinationType.TOPIC with the topic name.
- Check the version of the solace mapping classes matches the Beam SolaceIO version you use.
- If a temporary destination is needed, create it via the JCSMP session directly instead of the generic Destination mapping.
Example fix
// before
public Solace.DestinationType getType() { return Solace.DestinationType.TEMPORARY_QUEUE; }
// after
public Solace.DestinationType getType() { return Solace.DestinationType.QUEUE; } Defensive patterns
Strategy: type-guard
Validate before calling
// Validate destination types before submitting the write
// if (dest.getType() != Solace.DestinationType.TOPIC && dest.getType() != Solace.DestinationType.QUEUE)
// throw new IllegalArgumentException("Unsupported destination type: " + dest.getType()); Type guard
boolean isWritableDestination(Solace.Destination d) {
return d != null && (d.getType() == Solace.DestinationType.TOPIC || d.getType() == Solace.DestinationType.QUEUE);
} Try / catch
try { pipeline.run(); }
catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("SolaceIO.Write: Unknown destination type")) fixDestinationMapping();
else throw e;
} Prevention
- Only ever return TOPIC or QUEUE from custom Destination.getType() implementations.
- Unit-test custom destination mappings against SolaceIO before running the pipeline.
- Keep Beam's SolaceIO and the Solace mapping library versions aligned.
When it happens
Trigger: A custom Solace.Destination whose getType() is not TOPIC or QUEUE is supplied to SolaceIO.Write (custom destination mappings / subclassed Destination), reaching convertToJcsmpDestination during message serialization.
Common situations: Implementing a custom Destination with an invented type (e.g. TEMPORARY_TOPIC) unsupported by Beam's Solace writer; mapping library version mismatch returning an unexpected enum value.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Cannot create object with unspecified or no compression
- Failed to read broker response content
- invalid Class value
- Invalid initial position in stream
- Invalid watermark policy
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/aa4b00fa10689926.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/SolaceIO.java:457
/** Get a {@link Queue} object from the queue name. */
static Queue queueFromName(String queueName) {
return JCSMPFactory.onlyInstance().createQueue(queueName);
}
/**
* Convert to a JCSMP destination from a schema-enabled {@link
* org.apache.beam.sdk.io.solace.data.Solace.Destination}.
*
* <p>This method returns a {@link Destination}, which may be either a {@link Topic} or a {@link
* Queue}
*/
public static Destination convertToJcsmpDestination(Solace.Destination destination) {
if (destination.getType().equals(Solace.DestinationType.TOPIC)) {
return topicFromName(checkNotNull(destination.getName()));
} else if (destination.getType().equals(Solace.DestinationType.QUEUE)) {
return queueFromName(checkNotNull(destination.getName()));
} else {
throw new IllegalArgumentException(
"SolaceIO.Write: Unknown destination type: " + destination.getType());
}
}
/**
* Create a {@link Read} transform, to read from Solace. The ingested records will be mapped to
* the {@link Solace.Record} objects.
*/
public static Read<Solace.Record> read() {
return new Read<Solace.Record>(
Read.Configuration.<Solace.Record>builder()
.setTypeDescriptor(TypeDescriptor.of(Solace.Record.class))
.setParseFn(SolaceRecordMapper::toRecord)
.setTimestampFn(SENDER_TIMESTAMP_FUNCTION)
.setDeduplicateRecords(DEFAULT_DEDUPLICATE_RECORDS)
.setWatermarkIdleDurationThreshold(DEFAULT_WATERMARK_IDLE_DURATION_THRESHOLD)
.setAckDeadline(DEFAULT_ACK_DEADLINE)
.setNackOnTimeout(DEFAULT_NACK_ON_TIMEOUT));View on GitHub (pinned to 12126d8942)