moeru-ai/airi · error · Error

errors.empty-command

Error message

errors.empty-command

What it means

Thrown by buildConfigFile when a server row has a valid, unique identifier but its command field (after trim) is empty. translateMessage('errors.empty-command', { name }) resolves the locale string; note the message key itself is the thrown text shown here — the resolved translation is what the user sees. An MCP stdio server requires a command to spawn.

Source

Thrown at apps/stage-tamagotchi/src/renderer/pages/settings/modules/mcp-config.ts:102

/** Builds the persisted MCP config file from editable rows. */
export function buildConfigFile(
  servers: ServerForm[],
  translateMessage: TranslateMcpMessage,
): ElectronMcpStdioConfigFile {
  const config: ElectronMcpStdioConfigFile = { mcpServers: {} }
  const seenIdentifiers = new Set<string>()

  for (const [index, server] of servers.entries()) {
    const identifier = server.identifier.trim()
    if (!identifier)
      throw new Error(translateMessage('errors.empty-identifier', { index: index + 1 }))

    if (seenIdentifiers.has(identifier))
      throw new Error(translateMessage('errors.duplicate-identifier', { name: identifier }))

    if (!server.command.trim())
      throw new Error(translateMessage('errors.empty-command', { name: identifier }))

    seenIdentifiers.add(identifier)
    config.mcpServers[identifier] = buildServerConfig(server)
  }

  return config
}

/** Builds the JSON editor draft while preserving the current draft when form validation fails. */
export function syncJsonDraftFromServers(
  servers: ServerForm[],
  previousDraft: string,
  translateMessage: TranslateMcpMessage,
  formatError: (error: unknown) => string,
) {
  try {
    return {
      draft: `${JSON.stringify(buildConfigFile(servers, translateMessage), null, 2)}\n`,

View on GitHub (pinned to 27111382b4)

Solutions

  1. Enter the executable command for the server (e.g. 'npx', 'node', '/usr/local/bin/mcp-server').
  2. If the server is HTTP/SSE-based, use the appropriate transport config rather than the stdio form.
  3. Validate the command field is non-empty before enabling Save.
Defensive patterns

Strategy: validation

Validate before calling

function allServersHaveCommand(servers: ServerForm[]): boolean {
  return servers.every(s => s.command.trim().length > 0)
}

Type guard

function hasNonEmptyCommand(server: ServerForm): boolean {
  return typeof server.command === 'string' && server.command.trim().length > 0
}

Try / catch

try {
  buildConfigFile(servers, t)
} catch (e) {
  // point the user to the row missing a command
}

Prevention

When it happens

Trigger: User filled in a server name but left the command/executable blank, or entered only args/env without the binary path. The config object is built only after all three checks (identifier, duplicate, command) pass.

Common situations: User intended to use a URL/transport-based server but the form is stdio-only; command field cleared during editing; mis-pasted config omitted the command.

Related errors


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