multica-ai/multica · error

config must not be empty

Error message

config must not be empty

What it means

validateWorkspaceMcpServerEntry's third branch: the entry parsed as a JSON object but the object has zero keys ({}). An empty object gives the runtime nothing to mount — no command, URL, or transport — so it is rejected rather than stored as dead config. Same shallow-shape philosophy as the sibling checks.

Source

Thrown at server/internal/handler/workspace_mcp.go:173

}

// validateWorkspaceMcpServerEntry checks the shape of ONE server entry before
// it is stored. Deliberately shallow — shape only, never the contents, which
// are runtime-specific and carry secrets we do not want to inspect or echo
// back in an error.
func validateWorkspaceMcpServerEntry(raw json.RawMessage) error {
	trimmed := bytes.TrimSpace(raw)
	if len(trimmed) == 0 {
		return errors.New("config must be a JSON object")
	}
	var entry map[string]json.RawMessage
	if err := json.Unmarshal(trimmed, &entry); err != nil {
		// Never wrap: the underlying error can echo fragments of an entry that
		// routinely embeds API tokens.
		return errors.New("config must be a JSON object")
	}
	if len(entry) == 0 {
		return errors.New("config must not be empty")
	}
	return nil
}

// validateWorkspaceMcpServerName checks a server name. The name is what the
// runtime mounts the server under and what an agent's own config collides
// with, so it follows the same rule the agent settings dialog enforces.
func validateWorkspaceMcpServerName(name string) error {
	if name == "" {
		return errors.New("name is required")
	}
	for _, r := range name {
		switch {
		case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9', r == '-', r == '_':
		default:
			return errors.New("name may only contain letters, digits, hyphens, and underscores")
		}
	}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Omit the server entry until it has at least its transport fields (command or url)
  2. Require a minimal valid object in the form before enabling submit
  3. If deleting, remove the key from the servers map rather than leaving {}

Example fix

// before
servers: { github: {} }
// after
// omit until ready:
servers: { } // or
servers: { github: { command: "npx", args: ["-y", "@mcp/github"] } }
Defensive patterns

Strategy: validation

Validate before calling

const cleaned = Object.fromEntries(
  Object.entries(servers).filter(([, e]) => isMcpEntryObject(e) && Object.keys(e).length > 0)
);

Type guard

function isNonEmptyMcpEntry(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v) && Object.keys(v).length > 0;
}

Prevention

When it happens

Trigger: PUT/POST workspace MCP servers with an entry of {}. Typical when a form row was created but all its fields left blank, or a client sends {servers: {name: {}}} as a placeholder to 'reserve' a name.

Common situations: Add-server dialogs that submit the row on Enter before fields are filled; programmatic upserts initializing entries as {} to fill later; template interpolation producing no keys.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/ac94769e53291604. Report an issue: GitHub.