{"record":{"id":"590e32f5b9628c1d","repo":"ruvnet/ruflo","slug":"federationbridge-decode-payload-missing-required","errorCode":null,"errorMessage":"FederationBridge.decode: payload missing required fields","messagePattern":"FederationBridge\\.decode: payload missing required fields","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts","lineNumber":156,"sourceCode":"  }\n\n  /**\n   * Decode an incoming envelope back into the claim event + vclock + hlc\n   * tuple. Validates the envelope shape; does NOT verify the signature\n   * (that's the transport's job, before this method is called).\n   */\n  decode(envelope: FederationEnvelope): ClaimEventEnvelopePayload {\n    if (envelope.type !== CLAIM_EVENT_MESSAGE_TYPE) {\n      throw new Error(\n        `FederationBridge.decode: expected type '${CLAIM_EVENT_MESSAGE_TYPE}', got '${envelope.type}'`,\n      );\n    }\n    const payload = envelope.payload as ClaimEventEnvelopePayload;\n    if (!payload || typeof payload !== 'object') {\n      throw new Error('FederationBridge.decode: payload missing or non-object');\n    }\n    if (!payload.event || !payload.vclock || !payload.hlc || !payload.originNodeId) {\n      throw new Error('FederationBridge.decode: payload missing required fields');\n    }\n    return payload;\n  }\n}\n","sourceCodeStart":138,"sourceCodeEnd":161,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts#L138-L161","documentation":"decode requires all four payload fields — event, vclock, hlc, and originNodeId — to be present; missing any one throws. These carry the domain event, causal history, and origin identity, so a partial payload cannot be reconstructed into a federated claim event.","triggerScenarios":"A peer running an older bridge version that omits a field (commonly originNodeId); hand-serialized payloads; JSON round-trips that drop undefined keys; payloads built with object spread where some keys are undefined.","commonSituations":"Rolling upgrades with mixed node versions; abbreviated test fixtures; a producer that conditionally sets fields depending on message content.","solutions":["Publish only via encode(), which emits the full field set","Pin all federated nodes to a bridge version that emits event/vclock/hlc/originNodeId before admitting new traffic","Log the rejected envelope with its missing keys to identify the misbehaving producer quickly"],"exampleFix":"// before\nconst payload = bridge.decode(envelope);\n\n// after\nconst p = envelope.payload as Record<string, unknown>;\nfor (const k of ['event', 'vclock', 'hlc', 'originNodeId']) {\n  if (!p?.[k]) throw new Error(`envelope missing ${k}`);\n}\nconst payload = bridge.decode(envelope);","handlingStrategy":"type-guard","validationCode":"const p = envelope.payload as Record<string, unknown> | undefined;\nconst complete = !!p && !!p.event && !!p.vclock && !!p.hlc && !!p.originNodeId;\nif (!complete) { reject(envelope); } else { const payload = bridge.decode(envelope); }","typeGuard":"function isClaimEventPayload(p: unknown): p is ClaimEventEnvelopePayload {\n  if (typeof p !== 'object' || p === null) return false;\n  const o = p as Record<string, unknown>;\n  return !!o.event && !!o.vclock && !!o.hlc && !!o.originNodeId;\n}","tryCatchPattern":"try { payload = bridge.decode(envelope); }\ncatch (e) { if (e instanceof Error && e.message.includes('missing required fields')) { rejectWithDetail(envelope); } else throw e; }","preventionTips":["Never hand-assemble payloads; use encode() which always emits all four fields","Version gate federation peers: refuse mixed-version traffic during rolling upgrades","Log which field is missing to pinpoint the producer immediately"],"tags":["federation","protocol-validation","schema","typescript"],"backgroundTag":"missing-required-field","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}