From 7882355b136f4b9fa6e47a78dd091daa4711bd6b Mon Sep 17 00:00:00 2001
From: robertjamesprior <83608739+robertjamesprior@users.noreply.github.com>
Date: Fri, 25 Sep 2026 19:02:44 +0000
Subject: [PATCH 1/2] Document the KERNEL_CONNECTION_FAILED live view event
The live view client posts KERNEL_CONNECTION_FAILED to the parent frame once it
has given up starting the viewer. Add it to the parent-frame events table,
version-gate it, handle it in the detection sample, and document that the client
retries transient failures internally so an embedder does not remount on top of
a retry the client is already running.
---
browsers/live-view.mdx | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/browsers/live-view.mdx b/browsers/live-view.mdx
index 62862928..f481b755 100644
--- a/browsers/live-view.mdx
+++ b/browsers/live-view.mdx
@@ -100,6 +100,7 @@ When the live view is embedded in an iframe, the client posts messages to the pa
| `KERNEL_PLAYING` | `playing: true` | Video frames are rendering. |
| `KERNEL_PAUSED` | `playing: false` | Playback has stopped. |
| `KERNEL_CONNECTION_TIMEOUT` | `reason`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | The client's connection watchdog expired. Useful for diagnostics. |
+| `KERNEL_CONNECTION_FAILED` | `reason`, `attempts`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | The client has given up starting the viewer and will not try again until the iframe reloads. |
| `KERNEL_READ_ONLY_CHANGED` | `readOnly`, `requestId` | Acknowledges a `KERNEL_SET_READ_ONLY` request. |
### Accepted from the parent
@@ -111,6 +112,8 @@ When the live view is embedded in an iframe, the client posts messages to the pa
`KERNEL_CONNECTION_TIMEOUT`, `KERNEL_READ_ONLY_CHANGED` and `KERNEL_SET_READ_ONLY` require a recent browser image. `KERNEL_CONNECTED`, `KERNEL_PLAYING` and `KERNEL_PAUSED` are available on all current images, but `capabilities` is sent only by recent ones — older images post `{ type: 'KERNEL_CONNECTED', connected: true }`, so treat a missing `capabilities` as unknown rather than unsupported.
+ `KERNEL_CONNECTION_FAILED` requires a browser image that includes the connect-failure fix. On images without it the client fails silently instead, so treat a missing `KERNEL_CONNECTION_FAILED` as unknown rather than as a successful start, and keep gating on `KERNEL_PLAYING`.
+
Messages are exchanged with the parent origin derived from `document.referrer`. If the referrer is unavailable — for example under a restrictive `Referrer-Policy` — the client cannot resolve your origin and will reject `KERNEL_SET_READ_ONLY`.
@@ -140,6 +143,7 @@ window.addEventListener('message', (event) => {
if (event.origin !== liveViewOrigin) return;
if (event.data?.type === 'KERNEL_PLAYING') clearTimeout(watchdog);
if (event.data?.type === 'KERNEL_PAUSED') arm();
+ if (event.data?.type === 'KERNEL_CONNECTION_FAILED') showFallback(event.data);
});
arm();
@@ -147,6 +151,10 @@ arm();
Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. The watchdog behind it is cleared once negotiation begins, so a connection that stalls after that point never emits it. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.
+`KERNEL_CONNECTION_FAILED` is the terminal signal. It means the client has exhausted its attempts, or hit a failure it will not retry, and nothing further will happen until the iframe reloads. Surface a persistent message on it rather than remounting automatically: the failure is often a property of the browser environment, so a remount repeats it. `attempts` reports how many attempts were made before giving up.
+
+The client retries transient failures itself, up to three attempts one second apart. Internal retries are not reported to the parent, so `KERNEL_CONNECTION_TIMEOUT` is only posted on the final attempt, and a remount on that event duplicates a retry the client is already doing.
+
## Kiosk mode
Kiosk mode provides a fullscreen live view experience without browser UI elements like the address bar and tabs. You can enable kiosk mode when creating a browser by setting the `kiosk_mode` parameter to `true`.
From cc978cb2175082a69a55e8827ad123266fa874ca Mon Sep 17 00:00:00 2001
From: robertjamesprior <83608739+robertjamesprior@users.noreply.github.com>
Date: Fri, 25 Sep 2026 21:23:35 +0000
Subject: [PATCH 2/2] Document the KERNEL_CONNECTION_FAILED live view event
The client reports a failed connect to the parent frame as a single terminal
event, and both terminal events now carry a machine-readable reason instead of
prose.
- add KERNEL_CONNECTION_FAILED to the parent-frame events table
- document the shared reason set -- transport, signaling, media, peer,
unsupported, server -- so an embedder can branch on it without matching
message text
- note that a failed connect posts one of the two terminal events, never both,
and that the client does not retry a connect itself
- treat KERNEL_CONNECTION_TIMEOUT as terminal alongside it, and record the
older reason string on images that predate the fix
Version-gated on the browser image carrying kernel/kernel-images#417.
---
browsers/live-view.mdx | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/browsers/live-view.mdx b/browsers/live-view.mdx
index f481b755..db72d22b 100644
--- a/browsers/live-view.mdx
+++ b/browsers/live-view.mdx
@@ -99,10 +99,21 @@ When the live view is embedded in an iframe, the client posts messages to the pa
| `KERNEL_CONNECTED` | `connected`, `capabilities` (recent images only) | Signaling is established. Frames are not necessarily rendering yet. |
| `KERNEL_PLAYING` | `playing: true` | Video frames are rendering. |
| `KERNEL_PAUSED` | `playing: false` | Playback has stopped. |
-| `KERNEL_CONNECTION_TIMEOUT` | `reason`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | The client's connection watchdog expired. Useful for diagnostics. |
-| `KERNEL_CONNECTION_FAILED` | `reason`, `attempts`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | The client has given up starting the viewer and will not try again until the iframe reloads. |
+| `KERNEL_CONNECTION_TIMEOUT` | `reason`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | A connect stage ran out its bound without completing. `reason` names the stage. |
+| `KERNEL_CONNECTION_FAILED` | `reason`, `iceConnectionState`, `connectionState`, `signalingState`, `socketOpen` | The connect failed outright. `reason` says why. Nothing further happens until the iframe reloads. |
| `KERNEL_READ_ONLY_CHANGED` | `readOnly`, `requestId` | Acknowledges a `KERNEL_SET_READ_ONLY` request. |
+Both terminal events carry the same `reason`, so branch on it instead of matching message text:
+
+| `reason` | Meaning |
+| --- | --- |
+| `transport` | the socket never opened inside its bound, or closed before signaling |
+| `signaling` | the socket opened but no offer arrived inside its bound |
+| `media` | a peer exists but ICE never reached `checking` inside its bound |
+| `peer` | peer construction or the remote offer threw |
+| `unsupported` | the browser has no `RTCPeerConnection` |
+| `server` | the server closed the connect |
+
### Accepted from the parent
| Event | Payload | Effect |
@@ -112,14 +123,14 @@ When the live view is embedded in an iframe, the client posts messages to the pa
`KERNEL_CONNECTION_TIMEOUT`, `KERNEL_READ_ONLY_CHANGED` and `KERNEL_SET_READ_ONLY` require a recent browser image. `KERNEL_CONNECTED`, `KERNEL_PLAYING` and `KERNEL_PAUSED` are available on all current images, but `capabilities` is sent only by recent ones — older images post `{ type: 'KERNEL_CONNECTED', connected: true }`, so treat a missing `capabilities` as unknown rather than unsupported.
- `KERNEL_CONNECTION_FAILED` requires a browser image that includes the connect-failure fix. On images without it the client fails silently instead, so treat a missing `KERNEL_CONNECTION_FAILED` as unknown rather than as a successful start, and keep gating on `KERNEL_PLAYING`.
+ `KERNEL_CONNECTION_FAILED` requires a browser image that includes the connect-failure fix. On images without it the client fails silently instead, so treat a missing `KERNEL_CONNECTION_FAILED` as unknown rather than as a successful start, and keep gating on `KERNEL_PLAYING`. On images before that fix, `KERNEL_CONNECTION_TIMEOUT` carries `reason: 'connection timeout'` rather than a stage name.
Messages are exchanged with the parent origin derived from `document.referrer`. If the referrer is unavailable — for example under a restrictive `Referrer-Policy` — the client cannot resolve your origin and will reject `KERNEL_SET_READ_ONLY`.
### Detecting a viewer that never starts
-Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the one signal that distinguishes a working viewer from one that is still connecting or has silently failed. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived:
+Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived:
```typescript Typescript/Javascript
const iframe = document.querySelector('#kernel-live-view');
@@ -144,6 +155,7 @@ window.addEventListener('message', (event) => {
if (event.data?.type === 'KERNEL_PLAYING') clearTimeout(watchdog);
if (event.data?.type === 'KERNEL_PAUSED') arm();
if (event.data?.type === 'KERNEL_CONNECTION_FAILED') showFallback(event.data);
+ if (event.data?.type === 'KERNEL_CONNECTION_TIMEOUT') showFallback(event.data);
});
arm();
@@ -151,9 +163,9 @@ arm();
Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. The watchdog behind it is cleared once negotiation begins, so a connection that stalls after that point never emits it. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.
-`KERNEL_CONNECTION_FAILED` is the terminal signal. It means the client has exhausted its attempts, or hit a failure it will not retry, and nothing further will happen until the iframe reloads. Surface a persistent message on it rather than remounting automatically: the failure is often a property of the browser environment, so a remount repeats it. `attempts` reports how many attempts were made before giving up.
+`KERNEL_CONNECTION_FAILED` and `KERNEL_CONNECTION_TIMEOUT` are both terminal, and a failed connect posts one of them, never both. Whichever arrives, nothing further happens until the iframe reloads. Surface a persistent message rather than remounting blindly: a `peer` or `unsupported` reason is a property of the browser environment, so a remount repeats it, while a `transport` reason is worth one retry.
-The client retries transient failures itself, up to three attempts one second apart. Internal retries are not reported to the parent, so `KERNEL_CONNECTION_TIMEOUT` is only posted on the final attempt, and a remount on that event duplicates a retry the client is already doing.
+The client does not retry a connect itself, so whatever `reason` you get is the first failure, and whether to try again is your call.
## Kiosk mode