clone

a self-hosted sync node for lofi apps: jazz sync over iroh, ticket-gated, with no static ip or cloud needed

feat/write-expiry-groundwork
lofi-node / docs / site / troubleshooting.md
troubleshooting.md 3.2K rendered
1# Troubleshooting and compatibility23<!-- Source: FelineStateMachine/lofi-node README.md, docs/hosting-lofi-apps.md4 ("Validation status"), src/errors.ts, src/native/loader.ts. -->56The node's failure modes are designed to be nameable. Work from the signal you see.78## Mesh: `unavailable`910`status().mesh` reports `{ state: "unavailable", reason: … }` when the native transport could not11load; the Jazz server still runs LAN-only and `ticket()`/`pair()` throw `MeshUnavailableError`12rather than degrade silently. Causes, in resolution order:13141. An explicit `LOFI_NODE_IROH` path that doesn't exist.152. Running from source without building the native layer (`cargo build --release` in16 `native/iroh-js`).173. An unsupported platform — most notably **Windows**, a documented gap (the `*-gnu` build path18 needs a `libnode.dll` import library the upstream toolchain ships only for msvc). Windows nodes19 run LAN-only until that resolves.2021On **arm64 Linux** the limitation sits one layer deeper: the Jazz engine (jazz-napi) publishes no22linux-arm64-gnu build, so the node cannot start at all there. Release binaries and the container23image cover macOS arm64 and Linux x86_64 ([platform notes](beyond-the-lan.md)).2425The compiled binary embeds digest-pinned prebuilts; a cache extraction that doesn't match its pin26fails loudly rather than loading.2728## 401 `invalid_ticket`2930Unknown ticket, revoked ticket, or a sync-scoped ticket on an admin route — deliberately one answer31for all three. If a previously working app starts seeing it, the ticket was revoked: re-enroll with32a fresh one. If provisioning sees it, the ticket lacks `provision` scope.3334## WebSocket closes with 40013536The ticket was revoked mid-session. This is the live-revocation path working as designed; the app37should treat its stored sync location as dead and surface re-enrollment, not retry.3839## 502 `store_unavailable`4041The gate is up but its store is not — the loopback Jazz process, or on a leaf, the tunnel to the42root. Check `lofi-node status` and, for a leaf, `status().mesh.connections`.4344## Writes hang; nothing errors4546Almost always a store with **no deployed schema** — the engine hangs rather than fails in this47state. `GET <ticket-url>/store-status` reporting `{ "deployed": false }` confirms it; the remedy is48[provisioning](provision-a-store.md). lofi apps classify before attaching sync for exactly this49reason.5051## Version mismatch5253A node must run the **same Jazz alpha** as the apps it serves. Mismatches surface as protocol-level54failures (schema hash and catalogue errors) that no network configuration fixes. Confirm both pins55before debugging anything else.5657## Compatibility status, honestly5859The whole flow is validated end to end against lofi's reference app with real browser clients:60build, boot, offline edits, reconvergence, and the full provisioning lifecycle through the gate and61through an iroh-paired leaf. One known upstream finding: lofi's opt-in browser convergence gate62fails at its final stage with a catalogue error **identically against lofi-node and against lofi's63own first-party dev server** — a controlled experiment placing the issue in the pinned Jazz alpha,64not the node. lofi-node's contract docs carry the current validation table.