ruvnet/ruflo · error

FederationBridge.decode: payload missing or non-object

Error message

FederationBridge.decode: payload missing or non-object

What it means

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.

Source

Thrown at v3/@claude-flow/claims/src/infrastructure/federation-bridge.ts:153

    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

  1. Validate inbound envelopes at the transport boundary (payload must be an object) and quarantine rejects there with context
  2. Always build outbound envelopes via the bridge's encode() rather than hand-assembling them
  3. Add a schema check (e.g. zod) on the wire format before decode so failures carry the offending envelope

Example fix

// before
const payload = bridge.decode(envelope);

// after
if (typeof envelope.payload !== 'object' || envelope.payload === null) {
  throw new Error(`malformed envelope from ${envelope.sourceNodeId}: payload missing`);
}
const payload = bridge.decode(envelope);
Defensive patterns

Strategy: type-guard

Validate before calling

const ok = typeof envelope.payload === 'object' && envelope.payload !== null;
if (!ok) { quarantine(envelope); } else { const payload = bridge.decode(envelope); }

Type guard

function hasObjectPayload(e: FederationEnvelope): boolean {
  return typeof e.payload === 'object' && e.payload !== null;
}

Try / catch

try { payload = bridge.decode(envelope); }
catch (e) { if (e instanceof Error && e.message.includes('payload missing or non-object')) { quarantine(envelope); } else throw e; }

Prevention

When it happens

Trigger: 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 }.

Common situations: 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.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/358151e0d631b48d. Report an issue: GitHub.