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
- Omit the server entry until it has at least its transport fields (command or url)
- Require a minimal valid object in the form before enabling submit
- 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
- Don't submit placeholder {} rows from add-server dialogs
- Upsert real config in one step instead of reserving names with empty objects
- Require at least a command or url field before the row is submittable
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
- config must be a JSON object
- entry must be a JSON object
- local server missing required field `command`
- remote server missing required field `url`
- missing required field `type` (must be "local" or "remote",
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/ac94769e53291604.
Report an issue: GitHub.