{"record":{"id":"a8262714475fb1d9","repo":"googleapis/mcp-toolbox","slug":"toolset-q-declared-more-than-once","errorCode":null,"errorMessage":"toolset %q declared more than once","messagePattern":"toolset %q declared more than once","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/server/config.go","lineNumber":292,"sourceCode":"\t\t\t\ttoolConfigs = make(ToolConfigs)\n\t\t\t}\n\t\t\tif _, exists := toolConfigs[name]; exists {\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"tool %q declared more than once\", name)\n\t\t\t}\n\t\t\ttoolConfigs[name] = c\n\t\tcase \"toolset\":\n\t\t\tc, err := UnmarshalYAMLToolsetConfig(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 toolsetGroups == nil {\n\t\t\t\ttoolsetGroups = make(map[string]group.GroupConfig)\n\t\t\t}\n\t\t\tif _, exists := toolsetGroups[name]; exists {\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"toolset %q declared more than once\", name)\n\t\t\t}\n\t\t\ttoolsetGroups[name] = group.GroupConfig{Name: name, ToolNames: c.ToolNames}\n\t\tcase \"embeddingModel\":\n\t\t\tc, err := UnmarshalYAMLEmbeddingModelConfig(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 embeddingModelConfigs == nil {\n\t\t\t\tembeddingModelConfigs = make(EmbeddingModelConfigs)\n\t\t\t}\n\t\t\tif _, exists := embeddingModelConfigs[name]; exists {\n\t\t\t\treturn nil, nil, nil, nil, nil, nil, fmt.Errorf(\"embeddingModel %q declared more than once\", name)\n\t\t\t}\n\t\t\tembeddingModelConfigs[name] = c\n\t\tcase \"prompt\":","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/config.go#L274-L310","documentation":"UnmarshalPrimitiveConfig rejects duplicate toolset names: after unmarshaling a \"toolset\" document, it checks `toolsetGroups[name]` and errors if a toolset with that name was already declared. Duplicate names would silently replace an existing toolset group, so the parser fails fast.","triggerScenarios":"Calling ParseConfig with a YAML file (including multi-document files) that declares two `toolset` resources with the same name, triggering the `exists` check on `toolsetGroups`.","commonSituations":"Appending a second toolset block with a copy-pasted name; merging configs from teammates where both defined a toolset called `default` or `all-tools`.","solutions":["Rename one of the two toolsets named in the error to a unique name.","Delete the redundant duplicate toolset if unnecessary.","Grep the config for the duplicated name across all `---` documents.","If both toolsets share a purpose, merge their `toolNames` lists into one."],"exampleFix":"// before\ntoolsets:\n  default:\n    toolNames: [a, b]\n  default:\n    toolNames: [c]\n// after\ntoolsets:\n  default:\n    toolNames: [a, b]\n  admin-tools:\n    toolNames: [c]","handlingStrategy":"validation","validationCode":"func rawDuplicateToolsetNames(data string) []string {\n    var seen, dups []string\n    inSection := false\n    for _, line := range strings.Split(data, \"\\n\") {\n        trimmed := strings.TrimSpace(line)\n        if strings.HasPrefix(line, \"toolsets:\") { inSection = true; continue }\n        if strings.HasPrefix(line, \"tools:\") || strings.HasPrefix(line, \"prompts:\") { inSection = false }\n        if inSection && strings.HasSuffix(trimmed, \":\") && !strings.HasPrefix(trimmed, \"-\") {\n            name := strings.TrimSuffix(trimmed, \":\")\n            if slices.Contains(seen, name) { dups = append(dups, name) }\n            seen = append(seen, name)\n        }\n    }\n    return dups\n}","typeGuard":"func isDuplicateToolsetErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"toolset\") && strings.Contains(err.Error(), \"declared more than once\")\n}","tryCatchPattern":"cfg, err := server.ParseConfig(ctx, yamlBytes)\nif err != nil {\n    if strings.Contains(err.Error(), \"declared more than once\") {\n        return fmt.Errorf(\"dedupe toolset names in toolbox.yaml: %w\", err)\n    }\n    return err\n}","preventionTips":["Name toolsets after their audience/purpose (e.g., read-only-tools) to avoid collisions when merging.","Search all documents of a multi-doc file for a name before reusing it.","Enable a duplicate-key lint rule in yamllint configuration."],"tags":["config","duplicate","toolset","yaml"],"backgroundTag":"duplicate-resource-definition","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"}