{"record":{"id":"f2baee4d44efd0b0","repo":"github/github-mcp-server","slug":"failed-to-unmarshal-tools-w","errorCode":null,"errorMessage":"failed to unmarshal tools: %w","messagePattern":"failed to unmarshal tools: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/github-mcp-server/list_scopes.go","lineNumber":100,"sourceCode":"\t}\n\treturn scope\n}\n\nfunc runListScopes() error {\n\t// Get toolsets configuration (same logic as stdio command)\n\tvar enabledToolsets []string\n\tif viper.IsSet(\"toolsets\") {\n\t\tif err := viper.UnmarshalKey(\"toolsets\", &enabledToolsets); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unmarshal toolsets: %w\", err)\n\t\t}\n\t}\n\t// else: enabledToolsets stays nil, meaning \"use defaults\"\n\n\t// Get specific tools (similar to toolsets)\n\tvar enabledTools []string\n\tif viper.IsSet(\"tools\") {\n\t\tif err := viper.UnmarshalKey(\"tools\", &enabledTools); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unmarshal tools: %w\", err)\n\t\t}\n\t}\n\n\treadOnly := viper.GetBool(\"read-only\")\n\toutputFormat := viper.GetString(\"list-scopes-output\")\n\n\t// Create translation helper\n\tt, _ := translations.TranslationHelper()\n\n\t// Build inventory using the same logic as the stdio server\n\tinventoryBuilder := github.NewInventory(t).\n\t\tWithReadOnly(readOnly)\n\n\t// Configure toolsets (same as stdio)\n\tif enabledToolsets != nil {\n\t\tinventoryBuilder = inventoryBuilder.WithToolsets(enabledToolsets)\n\t}\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/cmd/github-mcp-server/list_scopes.go#L82-L118","documentation":"Returned by runListScopes when viper.UnmarshalKey(\"tools\", &enabledTools) fails — the configured 'tools' value cannot be decoded into []string. Like the toolsets key, it only runs when viper.IsSet(\"tools\") is true. Because tool names are later fed to inventory WithTools, a successful decode with wrong names will subsequently surface as ErrUnknownTools at Build(); this error is specifically a decode/type failure.","triggerScenarios":"Config sets tools to a non-list shape (map, number, nested object); an env/flag value that cannot be split/converted into a []string; malformed config syntax under the 'tools' key.","commonSituations":"Editing the config and writing 'tools: create_issue' (bare scalar in strict contexts) or a key/value block instead of a list; JSON configs using an object instead of an array; stale configs from older versions with a different schema.","solutions":["Write tools as a string list in the config: tools: [\"issue\", \"issue_comment\"]","Drop the key to use defaults, or list toolsets instead if you meant whole toolsets","Lint the config file for syntax and shape before running list-scopes","Confirm tool names against current docs so the value survives the later WithTools validation"],"exampleFix":"# before (config.yml)\ntools:\n  - name: issue\n    enabled: true\n\n# after\ntools: [\"issue\", \"issue_comment\"]","handlingStrategy":"validation","validationCode":"// Ensure the 'tools' config value is a plain string list before decoding\nraw := viper.Get(\"tools\")\nif raw != nil {\n    arr, ok := raw.([]any)\n    if !ok {\n        log.Fatalf(\"'tools' must be a list of tool names, got %T\", raw)\n    }\n    for _, e := range arr {\n        if _, ok := e.(string); !ok {\n            log.Fatalf(\"'tools' entries must be strings, got %T\", e)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"var enabledTools []string\nif viper.IsSet(\"tools\") {\n    if err := viper.UnmarshalKey(\"tools\", &enabledTools); err != nil {\n        log.Fatalf(\"invalid 'tools' config (must be a list of strings): %v\", err)\n    }\n}","preventionTips":["Write tools as an array of quoted names in config files","Use toolset names under 'toolsets', not 'tools'","After decoding, validate names against current docs to avoid the later ErrUnknownTools failure"],"tags":["configuration","viper","cli","type-mismatch","startup"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}