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

  1. Give each property a distinct header name
  2. If several inputs should feed one header, merge them into a single property or compose the value client-side
  3. 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

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


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)