siyuan-note/siyuan · warning

duplicate variable %q

Error message

duplicate variable %q

What it means

Validation error from validateMCPServerEnvironment: two keys in server.Env normalize to the same environmentKey. A Go map cannot hold two byte-identical keys, so on Unix this is effectively unreachable; on Windows, where environmentKey upper-cases the name, case-variant keys like 'Path' and 'PATH' collide. The second occurrence is reported via %q.

Source

Thrown at kernel/mcp/client/mcp.go:566

			return err
		}
		key := environmentKey(name, goos)
		if inherited[key] {
			return fmt.Errorf("duplicate inherited variable %q", name)
		}
		inherited[key] = true
	}
	explicit := map[string]bool{}
	for name, value := range server.Env {
		if err := validateEnvironmentName(name); err != nil {
			return err
		}
		if strings.ContainsRune(value, '\x00') {
			return fmt.Errorf("variable %q contains NUL", name)
		}
		key := environmentKey(name, goos)
		if explicit[key] {
			return fmt.Errorf("duplicate variable %q", name)
		}
		explicit[key] = true
	}
	return nil
}

// ValidateMCPServerEnvironment 校验当前平台上的 stdio 环境变量配置。
func ValidateMCPServerEnvironment(server conf.MCPServer) error {
	return validateMCPServerEnvironment(server, runtime.GOOS)
}

func defaultMCPEnvironmentNames(goos string) []string {
	if goos == "windows" {
		return []string{"APPDATA", "HOMEDRIVE", "HOMEPATH", "LOCALAPPDATA", "PATH", "PATHEXT",
			"PROCESSOR_ARCHITECTURE", "PROGRAMFILES", "SYSTEMDRIVE", "SYSTEMROOT", "TEMP", "USERNAME", "USERPROFILE"}
	}
	return []string{"HOME", "LOGNAME", "PATH", "SHELL", "TERM"}
}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. On Windows, keep only one casing of each variable name in Env and remove the case-variant duplicate.
  2. Normalize Env keys to a canonical case at config-load time on Windows.
  3. Run ValidateMCPServerEnvironment to confirm the duplicate is gone.

Example fix

// before (windows)
"env": {"PATH": "a", "Path": "b"}
// after
"env": {"PATH": "b"}
Defensive patterns

Strategy: validation

Validate before calling

import (
    "runtime"
    "strings"
)
func dedupeExplicit(env map[string]string) map[string]string {
    out := map[string]string{}
    for k, v := range env {
        key := k
        if runtime.GOOS == "windows" { key = strings.ToUpper(k) }
        out[key] = v
    }
    return out
}

Prevention

When it happens

Trigger: On Windows (runtime.GOOS == "windows"), server.Env contains two keys differing only in case, e.g. {"PATH": "a", "Path": "b"}. Both reduce to environmentKey "PATH"; the second triggers the error.

Common situations: Cross-platform config that tried to set the same variable under two casings; merging configs from different authors; a JSON merger that did not normalize case on Windows.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/2c73085ae2fa5eda. Report an issue: GitHub.