Submit an issue View all issues Source
MIR-1770

Cloud negotiates entity-sync/v1 but never processes snapshot.begin

Done public
phinze phinze Opened Sep 3, 2026 Updated Sep 4, 2026

Enabling appvisibility on garden for MIR-1762 gets through capability negotiation and then stalls. The runtime has been retrying every ~41 seconds since 21:59 UTC on 2026-09-03:

21:59:15  cloud export marker backfill complete │ scanned: 368 marked: 0 already_marked: 368
21:59:15  entity sync source preparation complete
21:59:33  entity sync source is ready
22:00:04  [WARN] start entity sync session │ error: "await entity.snapshot.complete ack:
                                                     context deadline exceeded" retry_in: 1s

Negotiation succeeds

The runtime's runSession returns early unless cloud selects the entity-sync capability and returns a Config whose export schema and source epoch both match locally. Garden got past all three checks and went on to snapshot, so cloud's Negotiate ran and its service is registered.

The negotiated digest is also the expected one. entity_sync_contracts holds exactly sha256:6b3c3d538a3f1b66747e6c88148985318181be8dfa063c3528e058b525f68ca3, registered by the migration at 2026-09-03 00:47:35, and that is byte-identical to core_v1alpha.CloudExportContract.Digest() at runtime main.

Nothing after negotiation lands

PostgresRepository.BeginSnapshot commits its own transaction, so a processed snapshot.begin would leave a visible row. There is none:

  • cluster_entity_sync where cluster_id = 6 returns 0 rows
  • cluster_entities where cluster_id = 6 returns 0 rows
  • cloud's web-service logs contain no entity-sync lines at all over the window, including the s.log.Warn paths inside Negotiate

So handler.HandleCapability works while router.Handle messages do not. Those are two different mechanisms registered side by side in Service.Register, and only the second one is failing. That points at the cluster-channel message router rather than at entity sync itself.

The symptom being a deadline rather than an error ack is consistent with the handler never running: handleSnapshotComplete returns before respondAck on a decode failure, and a handler that is never dispatched never acks at all.

Ruled out

  • **Wire format. **SnapshotBegin, SnapshotBatch, SnapshotComplete and Ack are field-for-field identical between runtime/pkg/entitysync/wire.go and cloud/services/entitysync/wire.go.
  • **Wrong deployment. **miren.cloud and eu1.miren.dev both resolve to 116.202.36.77, so the cloud app on the prod cluster is what garden is talking to. The database queried and the logs read are the right ones.
  • Source preparation. Marker backfill completed cleanly, and the gate opened.

Versions

  • garden runtime: main:09f83bc, which has the #1145 merge (0302254a) as an ancestor
  • cloud production: the manual miren deploy whose entity_sync migration executed 2026-09-03 00:47:35, so it includes #226. Note this predates runtime #1145 landing at 20:13, so a runtime change from #1145 without a cloud counterpart is worth checking first.

Notes

Garden currently still has MIREN_LABS=appvisibility set and is looping, which makes this a live repro. Entity sync is additive, so Anywhere and cloud RPC are unaffected. The original drop-in is saved at /etc/systemd/system/miren.service.d/override.conf.bak-mir1762 if it needs to be quieted.

Promotion to toys and club is stopped until this is understood.