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

  1. Pass a non-empty componentName such as 'weather' or 'extension-ui' when action is 'spawn'.
  2. 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.
  3. 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

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


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/f67a6dd8b1666b48. Report an issue: GitHub.