vercel/ai · warning · Error
Invalid ui/request-display-mode params
Error message
Invalid ui/request-display-mode params
What it means
The bridge validates `ui/request-display-mode` requests and requires `params.mode` to be exactly one of `inline`, `fullscreen`, or `pip`. Any other value (or non-object params) is rejected before reaching the host's requestDisplayMode handler.
Source
Thrown at packages/react/src/mcp-apps/bridge.ts:116
throw new Error(`Disallowed ui/open-link scheme: ${scheme}`);
}
return { url: params.url };
}
/**
* Validates params for `ui/request-display-mode`.
*/
function assertDisplayModeParams(params: unknown): {
mode: 'inline' | 'fullscreen' | 'pip';
} {
if (
!isJSONObject(params) ||
(params.mode !== 'inline' &&
params.mode !== 'fullscreen' &&
params.mode !== 'pip')
) {
throw new Error('Invalid ui/request-display-mode params');
}
return { mode: params.mode };
}
/**
* Host-side JSON-RPC bridge for one MCP App iframe.
*
* It handles the MCP Apps initialization handshake, sends tool input/result
* notifications to the iframe, and proxies allowed iframe requests through
* host-provided callbacks.
*
* @example
* ```ts
* const bridge = new MCPAppBridge({
* targetWindow: iframe.contentWindow!,
* handlers: {
* allowedTools: ['refreshDashboardData'],
* callTool: params => client.callTool(params),View on GitHub (pinned to 69428b1f8b)
Solutions
- Change the app to request only `inline`, `fullscreen`, or `pip`.
- Clamp/whitelist the computed mode value app-side before sending.
- Check the MCP Apps spec version used by the app for supported display modes.
- Inspect the rejected request via the host `onError` callback to see the actual mode value.
Example fix
// before
requestDisplayMode({ mode: 'maximized' })
// after
requestDisplayMode({ mode: 'fullscreen' }) Defensive patterns
Strategy: validation
Validate before calling
const MODES = ['inline', 'fullscreen', 'pip'] as const;
type Mode = typeof MODES[number];
function requestMode(mode: string): mode is Mode {
return (MODES as readonly string[]).includes(mode);
}
// before requesting:
if (!requestMode(desiredMode)) throw new Error(`Unsupported display mode: ${desiredMode}`); Type guard
function isDisplayMode(v: unknown): v is 'inline' | 'fullscreen' | 'pip' {
return v === 'inline' || v === 'fullscreen' || v === 'pip';
} Try / catch
try {
await requestDisplayMode({ mode });
} catch (error) {
if (error instanceof Error && error.message === 'Invalid ui/request-display-mode params') {
console.error(`mode must be inline|fullscreen|pip, got: ${mode}`);
}
} Prevention
- Only use the literal mode values inline, fullscreen, pip.
- Whitelist clamp dynamically computed modes before sending.
- Check the MCP Apps spec version supported by the host for valid modes.
- Type the mode as a union type app-side so invalid values fail at compile time.
When it happens
Trigger: The iframe posts `ui/request-display-mode` with `mode` set to something like `"maximized"`, `"window"`, `"popup"`, or with params missing/`mode` undefined.
Common situations: App written against an older or different MCP Apps draft that allowed other display modes; typo in the mode string; mode value dynamically computed and falling through to undefined.
Related errors
- Invalid tools/call params
- Invalid resources/read params
- Invalid ui/open-link params
- Invalid ui/open-link url: ${params.url}
- Invalid MCP App resource URI: ${JSON.stringify(resourceUri)}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/89c72d01b370a660.
Report an issue: GitHub.