Calling window.openai.setWidgetState() while requestDisplayMode({ mode: “fullscreen” }) transitions are occurring on iOS causes progressive rendering corruption. After 5–20 fullscreen open/close cycles:
- Interface mixing: inline content visible in fullscreen mode, or fullscreen content leaking into inline mode
- Progressive lag: each cycle adds latency before the display mode switch completes
- White screen: eventually the widget turns fully white (WKWebView crash)
Desktop and Android are unaffected.
Reproduction
Take the pizzaz-albums example from openai-apps-sdk-examples and add a useWidgetState call that syncs on data changes:
// pizzaz-albums/index.jsx — MODIFIED (crashes iOS after repeated fullscreen cycles)
import { useWidgetState } from “../use-widget-state”;
function App() {
const displayMode = useOpenAiGlobal(“displayMode”);
const toolOutput = useOpenAiGlobal(“toolOutput”);
const [selectedAlbum, setSelectedAlbum] = React.useState(null);
const maxHeight = useMaxHeight() ?? undefined;
// ⚠️ Adding this single hook causes the iOS crash:
const [widgetState, setWidgetState] = useWidgetState(() => ({ lastAlbumId: null }));
React.useEffect(() => {
if (toolOutput) {
setWidgetState({ lastAlbumId: selectedAlbum?.id }); // → window.openai.setWidgetState()
}
}, [toolOutput, selectedAlbum]);
// ... rest unchanged (handleSelectAlbum → requestDisplayMode("fullscreen"), conditional rendering)
}
Note: the original pizzaz-albums example never uses useWidgetState — it only usesrequestDisplayMode(“fullscreen”) with conditional rendering. That’s why it works fine on iOS.
Removing the setWidgetState() call eliminates the crash entirely — all other code unchanged.
Documentation gap
The state management docs say:
Treat it just like updating local component state and call it immediately after every meaningful UI-state change.
There is no mention of any interaction with requestDisplayMode on iOS. A warning in the docs would save developers significant debugging time.
Others threads report the same symptoms but did not identify setWidgetState as the trigger