{"record":{"id":"30e909018717d7c2","repo":"googleapis/mcp-toolbox","slug":"error-finding-yaml-files-in-q-w","errorCode":null,"errorMessage":"error finding YAML files in %q: %w","messagePattern":"error finding YAML files in %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/internal/config.go","lineNumber":549,"sourceCode":"\treturn configs[0], nil\n}\n\n// GetPathsFromConfigFolder loads all YAML files from a directory and merges them\nfunc GetPathsFromConfigFolder(ctx context.Context, folderPath string) ([]string, error) {\n\t// Check if directory exists\n\tinfo, err := os.Stat(folderPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to access config folder at %q: %w\", folderPath, err)\n\t}\n\tif !info.IsDir() {\n\t\treturn nil, fmt.Errorf(\"path %q is not a directory\", folderPath)\n\t}\n\n\t// Find all YAML files in the directory\n\tpattern := filepath.Join(folderPath, \"*.yaml\")\n\tyamlFiles, err := filepath.Glob(pattern)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error finding YAML files in %q: %w\", folderPath, err)\n\t}\n\n\t// Also find .yml files\n\tymlPattern := filepath.Join(folderPath, \"*.yml\")\n\tymlFiles, err := filepath.Glob(ymlPattern)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error finding YML files in %q: %w\", folderPath, err)\n\t}\n\n\t// Combine both file lists\n\tallFiles := append(yamlFiles, ymlFiles...)\n\treturn allFiles, nil\n}\n","sourceCodeStart":531,"sourceCodeEnd":563,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/cmd/internal/config.go#L531-L563","documentation":"GetPathsFromConfigFolder uses filepath.Glob to discover *.yaml files in the configured tools config directory. If Glob itself fails (it only fails on malformed patterns, e.g. ErrBadPattern), the function wraps the error and returns no paths. This is a wrapper around Go's standard library glob matching, not a 'no files found' condition.","triggerScenarios":"Calling GetPathsFromConfigFolder (via GetCustomConfigFiles) where filepath.Glob(filepath.Join(folderPath, \"*.yaml\")) returns a non-nil err — practically only when the joined pattern is malformed (e.g. folderPath contains an invalid glob escape like an unbalanced '[').","commonSituations":"A config folder path set via --tools-file/--prebuilt flags or env var containing glob metacharacters (brackets from oddly named directories), or programmatically constructed paths with unescaped pattern characters.","solutions":["Check the folderPath string for glob metacharacters ([, ], *, ?) and escape them with filepath.Escape or by fixing the path","Verify the path passed to --prebuilt/--tools-file config flags is a plain directory path, not a partial glob","Use filepath.Match error output (errors.Is(err, filepath.ErrBadPattern)) to confirm the pattern is malformed","Update the toolbox binary if the directory name is legitimate and the pattern joining is at fault"],"exampleFix":"// before\nfolderPath := \"configs/[drafts\" // unbalanced bracket -> ErrBadPattern\npaths, err := GetPathsFromConfigFolder(ctx, folderPath)\n// after\nfolderPath := filepath.Escape(\"configs/[drafts\")\npaths, err := GetPathsFromConfigFolder(ctx, folderPath)","handlingStrategy":"validation","validationCode":"for _, c := range folderPath {\n    if c == '[' || c == ']' {\n        return nil, fmt.Errorf(\"config folder path %q contains glob metacharacters\", folderPath)\n    }\n}\npaths, err := GetPathsFromConfigFolder(ctx, folderPath)","typeGuard":"func badGlobPath(p string) bool {\n    _, err := filepath.Match(p, \"\")\n    return errors.Is(err, filepath.ErrBadPattern)\n}","tryCatchPattern":null,"preventionTips":["Keep config directory paths free of glob metacharacters or escape them","Point --tools-file/--prebuilt at plain literal directory paths","Reproduce with filepath.Match before debugging the toolbox itself"],"tags":["go","filesystem","glob","config-loading"],"backgroundTag":"invalid-glob-pattern","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"}