ruvnet/ruflo · error
FederationBridge.decode: expected type 'claim-event', got '$
Error message
FederationBridge.decode: expected type 'claim-event', got '${envelope.type}' What it means
FederationBridge.decode only accepts envelopes whose type equals the claim-event message type ('claim-event'). A transport that multiplexes several message types will hand the decoder foreign envelopes; decode throws on the type mismatch instead of mis-parsing the payload. Signature verification is deliberately out of scope — it happens in the transport before decode runs.
Source
Thrown at v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts:147
event,
vclock,
originNodeId: this.opts.nodeId,
hlc,
},
};
await this.opts.transport.publish(envelope);
return envelope;
}
/**
* Decode an incoming envelope back into the claim event + vclock + hlc
* tuple. Validates the envelope shape; does NOT verify the signature
* (that's the transport's job, before this method is called).
*/
decode(envelope: FederationEnvelope): ClaimEventEnvelopePayload {
if (envelope.type !== CLAIM_EVENT_MESSAGE_TYPE) {
throw new Error(
`FederationBridge.decode: expected type '${CLAIM_EVENT_MESSAGE_TYPE}', got '${envelope.type}'`,
);
}
const payload = envelope.payload as ClaimEventEnvelopePayload;
if (!payload || typeof payload !== 'object') {
throw new Error('FederationBridge.decode: payload missing or non-object');
}
if (!payload.event || !payload.vclock || !payload.hlc || !payload.originNodeId) {
throw new Error('FederationBridge.decode: payload missing required fields');
}
return payload;
}
}
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Dispatch on envelope.type before decoding: only call decode when the type matches the claim-event constant
- Publish claim events on a dedicated topic/channel so foreign types cannot reach this decoder
- After any type rename, align the CLAIM_EVENT_MESSAGE_TYPE constant across all nodes before deploying
Example fix
// before
const payload = bridge.decode(envelope); // throws on heartbeats
// after
if (envelope.type === 'claim-event') {
const payload = bridge.decode(envelope);
} else {
handleOtherMessage(envelope);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (envelope.type !== 'claim-event') {
routeElsewhere(envelope); // heartbeat, handshake, custom types
} else {
const payload = bridge.decode(envelope);
} Type guard
function isClaimEventEnvelope(e: FederationEnvelope): boolean {
return e.type === 'claim-event';
} Try / catch
try { payload = bridge.decode(envelope); }
catch (e) { if (e instanceof Error && e.message.includes("expected type 'claim-event'")) { dropOrRoute(envelope); } else throw e; } Prevention
- Dispatch on message type at the transport boundary before any decoder sees the envelope
- Use a dedicated topic/channel per message type
- Bump and align type constants atomically across nodes during rolling upgrades
When it happens
Trigger: Routing a heartbeat, handshake, or custom envelope into FederationBridge.decode; a peer publishing claim events under a renamed type string after a schema change; hand-built test envelopes using type: 'claim' or 'ClaimEvent'.
Common situations: Shared message bus/channel carrying multiple message types with no type dispatch; version skew between bridge implementations after a type rename; test fixtures constructing envelopes by hand.
Related errors
- FederationBridge.decode: payload missing or non-object
- FederationBridge.decode: payload missing required fields
- Concurrent write detected on aggregate '${aggregateId}'. Res
- HLC skew exceeded: received physicalMs=${receivedPhysicalMs}
- Unsupported federation signature mode: ${String(signatureMod
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/c6581c70bf1dbc7c.
Report an issue: GitHub.