moeru-ai/airi · error · Error
componentName is required to spawn a widget.
Error message
componentName is required to spawn a widget.
What it means
Thrown by executeWidgetAction in the Stage desktop widget manager when action='spawn' but componentName is missing, empty, or whitespace-only. The spawn action must render a concrete Vue component, so the guard at widgets.ts:255 rejects any input where input.componentName?.trim() is falsy. It is a pre-dispatch validation gate before normalizeComponentProps, sanitization, and the IPC addWidget call.
Source
Thrown at apps/stage-tamagotchi/src/renderer/stores/tools/builtin/widgets.ts:255
return normalizeWidgetWindowSize(componentProps.windowSize)
}
function sanitizeComponentPropsForDispatch(componentName: string | undefined, componentProps: Record<string, any>) {
if (componentName?.trim().toLowerCase() !== 'extension-ui')
return componentProps
return sanitizeExtensionUiDispatchProps(componentProps)
}
export async function executeWidgetAction(input: WidgetActionInput, deps?: { invokers?: WidgetInvokers }) {
const invokers = resolveInvokers(deps?.invokers)
const normalizedId = input.id?.trim() || undefined
switch (input.action) {
case 'spawn': {
if (!input.componentName?.trim())
throw new Error('componentName is required to spawn a widget.')
const componentProps = normalizeComponentProps(input.componentProps)
const sanitizedComponentProps = sanitizeComponentPropsForDispatch(input.componentName, componentProps)
const windowSize = resolveWindowSize(input.componentName, sanitizedComponentProps, input.windowSize)
const ttlMs = input.ttlSeconds ? Math.floor(input.ttlSeconds * 1000) : 0
const id = await invokers.addWidget({
id: normalizedId,
componentName: input.componentName,
componentProps: sanitizedComponentProps,
size: input.size ?? 'm',
...(input.alwaysOnTop === undefined ? {} : { alwaysOnTop: input.alwaysOnTop }),
...(windowSize === undefined ? {} : { windowSize }),
ttlMs,
})
return `Spawned widget${id ? ` (${id})` : ''}.`
}
case 'update': {View on GitHub (pinned to 27111382b4)
Solutions
- Pass a non-empty componentName such as 'weather' or 'extension-ui' when action is 'spawn'.
- If building the call from an LLM tool result, validate componentName is present before dispatching, and fall back to prompting the model to supply it.
- For programmatic callers, narrow on the discriminated union: the spawn variant of WidgetActionInput marks componentName as required string — satisfy the type checker and the runtime guard will pass.
Example fix
// before
await executeWidgetAction({ action: 'spawn', id: 'w1', componentName: '', componentProps: {} })
// after
await executeWidgetAction({ action: 'spawn', id: 'w1', componentName: 'weather', componentProps: { city: 'Tokyo' } }) Defensive patterns
Strategy: validation
Validate before calling
function assertSpawnInput(input) {
if (input.action === 'spawn' && !input.componentName?.trim())
throw new Error('componentName is required to spawn a widget.')
}
// call before executeWidgetAction
assertSpawnInput(input) Type guard
function isSpawnReady(input) {
return input.action !== 'spawn' || Boolean(input.componentName?.trim())
} Try / catch
try {
await executeWidgetAction(input)
} catch (e) {
if (e.message.includes('componentName is required'))
// prompt the LLM/caller for componentName
throw e
} Prevention
- For LLM-driven calls, keep componentName in the tool schema as required and validate before dispatch.
- Unit-test the spawn path with a missing componentName to confirm the guard fires deterministically.
When it happens
Trigger: Calling executeWidgetAction({ action: 'spawn' }) or the stage_widgets tool with componentName omitted, set to '', or set to ' '. Also reached when an LLM driving the stage_widgets tool emits a spawn turn without populating componentName because the JSON schema field defaulted to empty.
Common situations: An LLM tool-call omits componentName while choosing action='spawn'; a test fixture constructs a WidgetActionInput spawn variant without componentName; a caller copies an 'open' or 'clear' payload shape (where componentName is optional) into a spawn call.
Related errors
- id is required to update a widget.
- id is required to remove a widget.
- Invalid Godot stage scene input payload.
- timeout must be a positive finite number
- Failed to apply server channel configuration
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/f67a6dd8b1666b48.
Report an issue: GitHub.