github/github-mcp-server · error
failed to unmarshal toolsets: %w
Error message
failed to unmarshal toolsets: %w
What it means
Returned by runListScopes when viper.UnmarshalKey("toolsets", &enabledToolsets) fails — i.e. the configured 'toolsets' value (from config file, env var, or flag) cannot be decoded into []string. It executes only when viper.IsSet("toolsets") is true, so any value shaped wrong for a string slice (a map, a nested object, a scalar of unexpected type) triggers it. This runs during the list-scopes command, i.e. at CLI startup before any GitHub API traffic.
Source
Thrown at cmd/github-mcp-server/list_scopes.go:91
_ = viper.BindPFlag("list-scopes-output", listScopesCmd.Flags().Lookup("output"))
rootCmd.AddCommand(listScopesCmd)
}
// formatScopeDisplay formats a scope string for display, handling empty scopes.
func formatScopeDisplay(scope string) string {
if scope == "" {
return "(no scope required for public read access)"
}
return scope
}
func runListScopes() error {
// Get toolsets configuration (same logic as stdio command)
var enabledToolsets []string
if viper.IsSet("toolsets") {
if err := viper.UnmarshalKey("toolsets", &enabledToolsets); err != nil {
return fmt.Errorf("failed to unmarshal toolsets: %w", err)
}
}
// else: enabledToolsets stays nil, meaning "use defaults"
// Get specific tools (similar to toolsets)
var enabledTools []string
if viper.IsSet("tools") {
if err := viper.UnmarshalKey("tools", &enabledTools); err != nil {
return fmt.Errorf("failed to unmarshal tools: %w", err)
}
}
readOnly := viper.GetBool("read-only")
outputFormat := viper.GetString("list-scopes-output")
// Create translation helper
t, _ := translations.TranslationHelper()
View on GitHub (pinned to 0ea1f775a7)
Solutions
- Set toolsets as a plain list of strings in the config file: toolsets: ["repos", "issues"] (YAML) or ["repos","issues"] (JSON/TOML array)
- Remove the toolsets key entirely to fall back to defaults (enabledToolsets stays nil)
- Validate the config file syntax (yaml/json linter) before running the command
- Print the effective value with viper (viper.Get("toolsets")) in a scratch program to see the actual decoded type
Example fix
# before (config.yml) toolsets: repos: enabled issues: enabled # after toolsets: ["repos", "issues"]
Defensive patterns
Strategy: validation
Validate before calling
// Validate the configured shape before it reaches viper's decoder
raw := viper.Get("toolsets")
switch raw.(type) {
case []string, []any, nil: // ok
default:
log.Fatalf("'toolsets' must be a list of strings, got %T", raw)
}
// stricter: ensure every element is a string
if arr, ok := raw.([]any); ok {
for _, e := range arr {
if _, ok := e.(string); !ok {
log.Fatalf("toolsets must be a list of strings; got element %T", e)
}
}
} Try / catch
var enabledToolsets []string
if viper.IsSet("toolsets") {
if err := viper.UnmarshalKey("toolsets", &enabledToolsets); err != nil {
// config shape problem: report and exit with a fix hint
log.Fatalf("invalid 'toolsets' config (must be a list of strings): %v", err)
}
} Prevention
- Always write toolsets as a YAML/JSON array of strings
- Lint config files (yamllint/json schema) before deploying
- Remove the key instead of setting it to a placeholder scalar to get defaults
When it happens
Trigger: Config file sets toolsets to a non-list value (e.g. YAML 'toolsets: {repos: enabled}' or 'toolsets: 123'); an env var or flag delivering a type that viper's decoder (mapstructure) cannot convert to []string; malformed JSON/YAML/TOML structure for that key.
Common situations: Hand-edited github-mcp-server config where toolsets is written as a map or scalar instead of a list; mixing config formats (JSON toolsets string vs list); version upgrades that changed the expected shape; env var GITHUB_TOOLSETS with bracket/brace characters parsed as structure.
Related errors
- failed to unmarshal tools: %w
- failed to build inventory: %w
- private key is %T, want an RSA key
- building installation token URL: %w
- creating installation token request: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/99b38016db8cb631.
Report an issue: GitHub.