{"record":{"id":"530d2beeafa8d1c8","repo":"googleapis/mcp-toolbox","slug":"more-than-one-default-nameless-group-declared-o","errorCode":null,"errorMessage":"more than one default (nameless) group declared; only one is allowed","messagePattern":"more than one default \\(nameless\\) group declared; only one is allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/server/config.go","lineNumber":338,"sourceCode":"\t\t\t}\n\t\t\tif _, exists := promptConfigs[name]; exists {\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"prompt %q declared more than once\", name)\n\t\t\t}\n\t\t\tpromptConfigs[name] = c\n\t\tcase \"group\":\n\t\t\tc, err := UnmarshalYAMLGroupConfig(ctx, name, resource)\n\t\t\tif err != nil {\n\t\t\t\tif len(file.Docs) > 1 {\n\t\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"document %d: error unmarshaling %s %q: %w\", docIndex, kind, name, err)\n\t\t\t\t}\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"error unmarshaling %s: %w\", kind, err)\n\t\t\t}\n\t\t\tif groupConfigs == nil {\n\t\t\t\tgroupConfigs = make(GroupConfigs)\n\t\t\t}\n\t\t\tif _, exists := groupConfigs[name]; exists {\n\t\t\t\tif name == \"\" {\n\t\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"more than one default (nameless) group declared; only one is allowed\")\n\t\t\t\t}\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"group %q declared more than once\", name)\n\t\t\t}\n\t\t\tgroupConfigs[name] = c\n\t\tdefault:\n\t\t\tif len(file.Docs) > 1 {\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"%s invalid kind %q\", formatDocLocation(docIndex, keyToken(doc.Body, \"kind\"), doc.Body), kind)\n\t\t\t}\n\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"invalid kind %s\", kind)\n\t\t}\n\t}\n\t// Fold legacy toolsets into groups. An explicit `kind: group` of the same name\n\t// takes precedence over a toolset (matching the prior server-side behavior); warn\n\t// when a toolset is shadowed this way.\n\tif len(toolsetGroups) > 0 {\n\t\tif groupConfigs == nil {\n\t\t\tgroupConfigs = make(GroupConfigs)\n\t\t}","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/config.go#L320-L356","documentation":"A config may contain at most one nameless (default) group; the default group applies to tools without an explicit group. If two group entries with an empty name decode successfully, UnmarshalPrimitiveConfig fails at internal/server/config.go:338 with this explicit message.","triggerScenarios":"Two 'group' resources in the YAML both have an empty name (two anonymous/default group blocks), so the second insertion into the groupConfigs map hits the exists check and the name=='' branch.","commonSituations":"Repeating a default group block when merging configs; YAML anchors accidentally producing two nameless groups; copy-pasting a group template and deleting its name in more than one place.","solutions":["Remove one of the nameless group blocks so only a single default group remains","Give the other group an explicit unique name if both sets of tools must be grouped","After merging configs, deduplicate group definitions before deploying"],"exampleFix":"# before\nkind: group\n:\n  toolIds: [tool-a]\n---\nkind: group\n:\n  toolIds: [tool-b]\n# after\nkind: group\n:\n  toolIds: [tool-a, tool-b]","handlingStrategy":"validation","validationCode":"// Count nameless groups in a config before parsing\ntext, _ := os.ReadFile(path)\ndocs := strings.Split(string(text), \"\\n---\")\ndefaults := 0\nfor _, d := range docs {\n\tvar doc struct {\n\t\tKind string `yaml:\"kind\"`\n\t\tName string `yaml:\"serverRef\"`\n\t}\n\tif yaml.Unmarshal([]byte(d), &doc) == nil && doc.Kind == \"group\" && strings.TrimSpace(d) != \"\" {\n\t\t// a group doc with no name key is a default group; count via key scan\n\t\tif !regexp.MustCompile(`(?m)^\\s+[\\w-]+:`).MatchString(strings.TrimPrefix(d, \"kind: group\")) == false && !strings.Contains(d, \"my-group\") {\n\t\t\tdefaults++\n\t\t}\n\t}\n}\nif defaults > 1 {\n\treturn fmt.Errorf(\"%d default groups found; keep at most one\", defaults)\n}","typeGuard":null,"tryCatchPattern":"if _, _, _, _, _, _, err := server.ParseConfig(ctx, cfg); err != nil {\n\tif strings.Contains(err.Error(), \"default (nameless) group\") {\n\t\tlog.Fatalf(\"config has multiple default groups: %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Declare exactly one anonymous group block per config, and only when needed","Prefer explicitly named groups over the nameless default","After merging configs, grep for repeated 'kind: group' blocks without names"],"tags":["yaml","config","group","duplicate","default"],"backgroundTag":"duplicate-config-key","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}