In dogfooding with mixed Marmot implementations, invitees sometimes receive and decrypt welcome events but fail to join the group.
Observed error (surfaced by joinGroupFromWelcome()):
Failed to join group with any matching key package. Last error: non-blank intermediate node must list leaf node in its unmerged_leaves
This points to strict ratchet-tree validation failure in ts-mls (see validateRatchetTree(), specifically the unmerged_leaves invariant around arraysEqual(...)).
Context
- Environment had multiple users/admins and mixed implementations.
- Some clients were known to do aggressive self-update behavior.
- Symptoms are consistent with state fork/drift around invite/join windows rather than transport/inbox failure.
Why this matters
A single divergent implementation can destabilize onboarding for new members by producing/propagating welcomes tied to inconsistent tree state. This creates poor interoperability and difficult-to-debug failures.
Analysis branch + doc
Likely root causes (ranked)
- Ratchet tree consistency drift in mixed implementations (most likely).
- Stale/divergent commit producer state under concurrent admin activity.
Contributors include:
- aggressive self-updates near join/invite timing
- concurrent membership-changing commits
- delayed/out-of-order ingestion
- implementation differences in sequencing/proposal handling
Proposed actions (future iteration)
- Add structured typed join errors (e.g.
WELCOME_TREE_INCONSISTENT) in joinGroupFromWelcome().
- Add targeted join diagnostics (candidate refs, per-attempt inner errors, welcome/tree metadata).
- Add optional interop-safe commit mode in
MarmotGroup.commit() to serialize risky transitions.
- Add drift/fork preflight checks before creating new commits.
- Add welcome quality gates before send path around
createWelcomeRumor().
- Add quarantine policy for repeatedly incompatible client fingerprints.
- Expand race/interop tests near
ingest-commit-race.test.ts and end-to-end-invite-join-message.test.ts.
Non-goal
Do not weaken MLS validation to accept inconsistent tree states. The fix direction is stronger diagnostics, safer sequencing, and better interop guardrails.
In dogfooding with mixed Marmot implementations, invitees sometimes receive and decrypt welcome events but fail to join the group.
Observed error (surfaced by
joinGroupFromWelcome()):This points to strict ratchet-tree validation failure in
ts-mls(seevalidateRatchetTree(), specifically theunmerged_leavesinvariant aroundarraysEqual(...)).Context
Why this matters
A single divergent implementation can destabilize onboarding for new members by producing/propagating welcomes tied to inconsistent tree state. This creates poor interoperability and difficult-to-debug failures.
Analysis branch + doc
docs/invite-join-drift-analysisdocumentation/invite-join-drift-analysis.mdLikely root causes (ranked)
Contributors include:
Proposed actions (future iteration)
WELCOME_TREE_INCONSISTENT) injoinGroupFromWelcome().MarmotGroup.commit()to serialize risky transitions.createWelcomeRumor().ingest-commit-race.test.tsandend-to-end-invite-join-message.test.ts.Non-goal
Do not weaken MLS validation to accept inconsistent tree states. The fix direction is stronger diagnostics, safer sequencing, and better interop guardrails.