---
title: "Say when the network is gone · Agent Wranglers"
url: https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/offline-behaviour
updated: 2026-10-20
licence: "All rights reserved"
---

# Say when the network is gone

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Permissions, flags and failures](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures)
- Rule: When the connection drops, say so in a banner and keep everything already loaded on screen. Either queue changes with idempotency keys and send them on reconnect, or block them with a reason.
- How: Treat a failed fetch as offline, and use the `offline` and `online` events as hints only. Keep loaded data readable. For apps used on the move, store pending changes in IndexedDB, each with its idempotency key, and send them in order when back online. Show how many changes are waiting. Caching pages is covered in [offline support](https://agentwranglers.se/playbook/website/when-things-break/offline-support).
- Check: A browser test goes offline, edits two records and goes back online. The banner shows while offline, and the server has both changes exactly once.

Example:

```ts
export async function sendOrQueue(change: PendingChange) {
  try {
    await apiFetch(change.url, { method: change.method, body: JSON.stringify(change.body), headers: { 'Idempotency-Key': change.key, 'Content-Type': 'application/json' } });
  } catch (error) {
    if (!(error instanceof TypeError)) throw error;
    await pendingChanges.add(change);
    showOfflineBanner(await pendingChanges.count());
  }
}

addEventListener('online', () => pendingChanges.sendAllInOrder());
```

```python
from playwright.sync_api import expect

def test_offline_edits_arrive_once(page, context):
    page.goto("https://staging.example.com/tasks")
    context.set_offline(True)
    page.get_by_role("checkbox", name="Call the printer").check()
    page.get_by_role("checkbox", name="Order new labels").check()
    expect(page.get_by_role("status")).to_contain_text("offline")
    context.set_offline(False)
    expect(page.get_by_role("status")).to_contain_text("All changes saved")
    assert tasks.change_count("task_77") == 1
    assert tasks.change_count("task_78") == 1
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/offline-behaviour`.

- Previous: [Give every request a time limit](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/request-timeouts)
- Next: [Recover when a new release replaces the old files](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/new-release-reload)
- [Permissions, flags and failures](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures)
