{"record":{"id":"358151e0d631b48d","repo":"ruvnet/ruflo","slug":"federationbridge-decode-payload-missing-or-non-ob","errorCode":null,"errorMessage":"FederationBridge.decode: payload missing or non-object","messagePattern":"FederationBridge\\.decode: payload missing or non-object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts","lineNumber":153,"sourceCode":"\n    await this.opts.transport.publish(envelope);\n    return envelope;\n  }\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":135,"sourceCodeEnd":161,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts#L135-L161","documentation":"After the type check passes, decode requires envelope.payload to be a non-null object. A null, undefined, string, or number payload means the envelope itself is malformed — publisher bug, truncated transport message, or schema drift — and decode refuses to cast it to ClaimEventEnvelopePayload.","triggerScenarios":"A publisher sends an envelope with payload omitted or set to a scalar; a JSON transport drops the field; a test constructs FederationEnvelope with only { type }.","commonSituations":"Partial envelope construction in unit tests; a renamed payload field after a protocol change; deserializers that skip missing keys and hand decode an incomplete object.","solutions":["Validate inbound envelopes at the transport boundary (payload must be an object) and quarantine rejects there with context","Always build outbound envelopes via the bridge's encode() rather than hand-assembling them","Add a schema check (e.g. zod) on the wire format before decode so failures carry the offending envelope"],"exampleFix":"// before\nconst payload = bridge.decode(envelope);\n\n// after\nif (typeof envelope.payload !== 'object' || envelope.payload === null) {\n  throw new Error(`malformed envelope from ${envelope.sourceNodeId}: payload missing`);\n}\nconst payload = bridge.decode(envelope);","handlingStrategy":"type-guard","validationCode":"const ok = typeof envelope.payload === 'object' && envelope.payload !== null;\nif (!ok) { quarantine(envelope); } else { const payload = bridge.decode(envelope); }","typeGuard":"function hasObjectPayload(e: FederationEnvelope): boolean {\n  return typeof e.payload === 'object' && e.payload !== null;\n}","tryCatchPattern":"try { payload = bridge.decode(envelope); }\ncatch (e) { if (e instanceof Error && e.message.includes('payload missing or non-object')) { quarantine(envelope); } else throw e; }","preventionTips":["Build outbound envelopes exclusively with encode()","Schema-check inbound envelopes at the transport and reject before decode","Include envelope IDs in quarantine logs to trace the misbehaving publisher"],"tags":["federation","protocol-validation","payload","typescript"],"backgroundTag":"malformed-payload","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}