KubeMQ
ConnectorsSTOMPHow-to guides

Protocol versions

STOMP 1.0/1.1/1.2 on the KubeMQ connector — version negotiation from accept-version, the per-version feature matrix, header escaping, and ack token rules.

The KubeMQ STOMP connector speaks STOMP 1.0, 1.1, and 1.2. The version is chosen during the CONNECT handshake from your accept-version header — the connector picks the highest common of {1.0, 1.1, 1.2}. A missing or empty accept-version defaults to 1.0; if there is no common version the connector returns an ERROR and closes.

Use accept-version:1.2. Every example sends accept-version:1.2. 1.2 is the only version that can escape \r (CR) in header values, uses the explicit ack token, and stamps the subscription header on MESSAGE frames. 1.0 and 1.1 are supported for compatibility with older clients.

Version negotiation

  • accept-version is comma-separated, order-independent, and whitespace-tolerant (1.2, 1.1 and 1.1,1.2 both negotiate 1.2).
  • Unknown tokens are ignored (1.0,9.9 → 1.0).
  • No common versionERROR carrying version:1.0,1.1,1.2 + close.

The negotiated version is echoed back on the CONNECTED frame's version header and surfaces as version in the management API connection record.

Feature matrix

Feature1.01.11.2Notes
Highest-common negotiationYesYesYesmissing/empty accept-version1.0
Header escapingnone\n,\c,\\\n,\c,\\,\rapplied only to non-CONNECT/STOMP frames once negotiated
\r (CR) representable in a header valueNoNoYes1.0/1.1 drop CR on egress
Repeated header → first value winsYesYesYesall occurrences preserved in arrival order
SUBSCRIBE id requiredNo — auto auto-NYesYesmissing id on 1.1/1.2 → invalid subscription
MESSAGE subscription headeromittedYesYesidentifies the matching subscription
MESSAGE ack token (opaque UUID)NoNoYes1.2-only; distinct from message-id
ACK/NACK correlationmessage-id → oldest pendingmessage-id + subscriptionid:<ack-token>per-version, connection-scoped
client / client-individual ackYes (lenient)YesYesaccepted on 1.0 too (ActiveMQ-style)
NACKYes (lenient)YesYeshonored on 1.0 too
UNSUBSCRIBE by destination (no id)Yes (fallback)NoNo1.0-only leniency
CRLF line endings toleratedYesYesYesa trailing \r is stripped on read (all versions)

Header escaping per version

Header escaping applies to both the header name and value, but only on the negotiated 1.1/1.2 version and only for non-CONNECT/STOMP frames. The handshake is exempt: CONNECT and STOMP frames are never unescaped, and CONNECTED is never escaped. 1.0 does no escaping at all.

Escape sequenceDecodes to1.01.11.2
\nLFliteralYesYes
\c:literalYesYes
\\\literalYesYes
\rCRliteralfatal malformed frameYes
any other (\t, …)literalfatalfatal

Columns are the STOMP version negotiated via the CONNECT accept-version header.

On 1.1, an \r escape (or any undefined escape) is a fatal malformed frame. A trailing lone backslash is fatal. A repeated header resolves to its first value (all occurrences are still preserved in arrival order).

CR/LF in a header value is silently dropped to 1.0/1.1 subscribers. STOMP 1.1 has no escape for CR, and 1.0 has no escaping at all, so the egress representability guard drops any header it cannot serialize (rather than corrupting the frame) and the connection stays alive. Use accept-version:1.2 for any binary or special-character scenario, and keep CR/LF out of header values — structured or multiline metadata belongs in the body. See Destination mapping for the full per-version representability table.

SUBSCRIBE id rules

Versionid on SUBSCRIBEBehavior
1.0optionalauto-generated auto-N when absent
1.1 / 1.2requiredmissing/empty idERROR "invalid subscription" / "id header required" + close

Per-version ACK token source

The 1.2 ack token is an opaque UUID emitted on the MESSAGE frame, distinct from message-id, and the only correct way to ACK on 1.2. On 1.1 you ACK by message-id + subscription; on 1.0 by message-id alone, which resolves to the oldest pending delivery on the connection.

VersionMESSAGE carriesACK/NACK by
1.2subscription, ack=UUID token, message-idid:<ack-token>
1.1subscription, message-id (no ack)message-id + subscription
1.0message-id only (no subscription, no ack)message-id → oldest pending

See Ack modes and receipts for the full ACK flow.

1.0 leniency (compatibility)

The connector applies ActiveMQ-style leniency on 1.0, beyond the strict 1.0 spec:

  • Auto subscription ids (auto-N) when SUBSCRIBE omits id.
  • client-individual and client ack modes accepted on 1.0 (not in the 1.0 spec).
  • NACK accepted and honored on 1.0.
  • UNSUBSCRIBE by destination (without id) — the connector removes the first matching subscription.

These are conveniences for legacy clients. Do not depend on them for portability — prefer accept-version:1.2.

Was this page helpful?

On this page