siyuan-note/siyuan · error
property : duplicate x-mcp-header value
Error message
property %q: duplicate x-mcp-header value %q
What it means
Two different properties in a tool schema must not map to the same HTTP header. Validation lowercases each x-mcp-header value and keeps a seen-set; a duplicate (case-insensitive) is rejected to avoid ambiguous or overwriting header injection at request time.
Solutions
- Give each property a distinct header name
- If several inputs should feed one header, merge them into a single property or compose the value client-side
- Remove the redundant x-mcp-header from the duplicate property
Example fix
// before
{"a":{"x-mcp-header":"X-Id"},"b":{"x-mcp-header":"x-id"}}
// after
{"a":{"x-mcp-header":"X-Id"},"b":{"x-mcp-header":"X-Alt-Id"}} Defensive patterns
Strategy: validation
Validate before calling
function checkHeaderUniqueness(schema) {
const seen = new Set();
for (const prop of Object.values(schema.properties || {})) {
const h = prop['x-mcp-header'];
if (typeof h === 'string') {
const k = h.toLowerCase();
if (seen.has(k)) throw new Error(`duplicate x-mcp-header: ${h}`);
seen.add(k);
}
}
} Type guard
null
Try / catch
try { registerTool(schema) } catch (e) { if (String(e).includes('duplicate x-mcp-header')) renameHeadersAndRetry(schema); else throw e; } Prevention
- Keep a single source of truth mapping properties to headers
- Compare header names case-insensitively when designing schemas
- Merge multi-input values into one property instead of reusing a header
When it happens
Trigger: A tool schema where two properties both declare x-mcp-header with the same name (even differing in case, e.g. "X-Auth" and "x-auth") during schema validation.
Common situations: Copy-pasting a property and forgetting to change the header, multiple optional params intended to fill one header, generated schemas merging overlapping mappings.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- property : x-mcp-header can only be applied to primitive…
- property : x-mcp-header must be a non-empty string
- property : x-mcp-header value is not a valid HTTP field name
- invalid input schema
- invalid output schema
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/11f9f935d2643f41.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/tools/validation.go:253
if prefix != "" {
path = prefix + "." + propertyName
}
if rawHeader, exists := property["x-mcp-header"]; exists {
header, ok := rawHeader.(string)
if !ok || header == "" {
return fmt.Errorf(`property %q: x-mcp-header must be a non-empty string`, path)
}
propertyType, _ := property["type"].(string)
if propertyType != "string" && propertyType != "integer" && propertyType != "boolean" {
return fmt.Errorf(
`property %q: x-mcp-header can only be applied to primitive types (integer, string, boolean), got %q`,
path, propertyType)
}
if !validHTTPFieldName(header) {
return fmt.Errorf(`property %q: x-mcp-header value %q is not a valid HTTP field name`, path, header)
}
normalized := strings.ToLower(header)
if seen[normalized] {
return fmt.Errorf(`property %q: duplicate x-mcp-header value %q`, path, header)
}
seen[normalized] = true
}
nested, _ := property["properties"].(map[string]any)
if err := walk(nested, path); err != nil {
return err
}
}
return nil
}
return walk(properties, "")
}
func validHTTPFieldName(name string) bool {
if name == "" {
return false
}View on GitHub (pinned to 9f775e8a12)