warpdotdev/warp · error · anyhow::Error
MCP server '{name}' field 'warp_id' must be non-empty
Error message
MCP server '{name}' field 'warp_id' must be non-empty What it means
Thrown when an MCP server entry's warp_id is a string that trims to empty and the WellKnownMcpIds flag is enabled (with the flag off, an empty string fails UUID parsing and hits the UUID error instead). It guards the well-known-id bucket from blank values so empty slugs never silently match a server.
Source
Thrown at app/src/ai/agent_sdk/config_file.rs:130
) -> anyhow::Result<Vec<MCPSpec>> {
let mut uuids: Vec<uuid::Uuid> = Vec::new();
let mut well_known: Vec<String> = Vec::new();
let mut json_map: Map<String, Value> = Map::new();
for (name, config) in mcp_servers {
let obj = config
.as_object()
.ok_or_else(|| anyhow::anyhow!("MCP server '{name}' config must be a JSON object"))?;
if let Some(warp_id) = obj.get("warp_id").and_then(Value::as_str) {
if let Ok(uuid) = uuid::Uuid::parse_str(warp_id) {
uuids.push(uuid);
} else if !FeatureFlag::WellKnownMcpIds.is_enabled() {
return Err(anyhow::anyhow!(
"MCP server '{name}' field 'warp_id' must be a UUID"
));
} else if warp_id.trim().is_empty() {
return Err(anyhow::anyhow!(
"MCP server '{name}' field 'warp_id' must be non-empty"
));
} else {
well_known.push(warp_id.to_string());
}
} else {
json_map.insert(name.clone(), config.clone());
}
}
uuids.sort();
uuids.dedup();
well_known.sort();
well_known.dedup();
let mut specs: Vec<MCPSpec> = uuids.into_iter().map(MCPSpec::Uuid).collect();
specs.extend(well_known.into_iter().map(MCPSpec::WellKnown));
View on GitHub (pinned to e72fd7aacb)
Solutions
- Fill in a real warp_id value (UUID, or a well-known slug on builds that support it).
- Remove the warp_id key entirely if the server should be treated as an inline command/url config.
- Lint configs for empty-string values before shipping: jq '.mcp_servers | to_entries | map(select(.value.warp_id? == "")) | length == 0'.
Example fix
// before
"mcp_servers": { "db": { "warp_id": "" } }
// after (inline server, no warp_id)
"mcp_servers": { "db": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres"] } } Defensive patterns
Strategy: validation
Validate before calling
if let Some(warp_id) = obj.get("warp_id").and_then(Value::as_str) {
anyhow::ensure!(!warp_id.trim().is_empty(), "warp_id must not be blank");
} Type guard
fn is_non_blank(s: &str) -> bool {
!s.trim().is_empty()
} Try / catch
match mcp_specs_from_mcp_servers(&mcp_servers) {
Err(err) if err.to_string().contains("must be non-empty") => fix_blank_warp_id_and_retry(&mcp_servers),
rest => rest,
} Prevention
- Fill or remove placeholder warp_id keys before shipping configs.
- Lint for empty-string values when generating configs from templates or YAML conversion.
- Prefer omitting warp_id over blanking it — blank buys nothing and fails parsing.
When it happens
Trigger: Config contains {"server": {"warp_id": ""}} or {"warp_id": " "} while FeatureFlag::WellKnownMcpIds is on: Uuid::parse_str fails, the flag branch is taken, and warp_id.trim().is_empty() routes to this error.
Common situations: Template-generated configs that leave warp_id as an empty placeholder; YAML-to-JSON conversion emitting an empty string for a null field; or an editor auto-completing the key without a value.
Related errors
- MCP server '{name}' config must be a JSON object
- MCP server '{name}' field 'warp_id' must be a UUID
- No environments are configured for this account. You can cre
- File is too large ({}MB). Maximum size is 10MB.
- could not determine home directory
AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16).
Data as JSON: /api/errors/9495b5d30fb26956.
Report an issue: GitHub.