{"record":{"id":"4bcdd8c000c70331","repo":"googleapis/mcp-toolbox","slug":"unable-to-read-config-file-at-q-w","errorCode":null,"errorMessage":"unable to read config file at %q: %w","messagePattern":"unable to read config file at %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/internal/config.go","lineNumber":511,"sourceCode":"\t\tif genericService, ok := authService.(generic.Config); ok && genericService.McpEnabled {\n\t\t\tmcpEnabledAuthServers = append(mcpEnabledAuthServers, name)\n\t\t}\n\t}\n\tif len(mcpEnabledAuthServers) > 1 {\n\t\treturn Config{}, fmt.Errorf(\"multiple authServices with mcpEnabled=true detected: %s. Only one MCP authorization server is currently supported\", strings.Join(mcpEnabledAuthServers, \", \"))\n\t}\n\n\treturn merged, nil\n}\n\n// LoadAndMergeConfigs loads multiple YAML files and merges them\nfunc (p *ConfigParser) LoadAndMergeConfigs(ctx context.Context, filePaths []string) (Config, error) {\n\tvar configs []Config\n\n\tfor _, filePath := range filePaths {\n\t\tbuf, err := os.ReadFile(filePath)\n\t\tif err != nil {\n\t\t\treturn Config{}, fmt.Errorf(\"unable to read config file at %q: %w\", filePath, err)\n\t\t}\n\n\t\tconfig, err := p.ParseConfig(ctx, buf)\n\t\tif err != nil {\n\t\t\treturn Config{}, fmt.Errorf(\"unable to parse config file at %q: %w\", filePath, err)\n\t\t}\n\n\t\tconfigs = append(configs, config)\n\t}\n\tif len(configs) == 0 {\n\t\treturn Config{}, fmt.Errorf(\"no YAML files found\")\n\t}\n\tif len(configs) > 1 {\n\t\tmergedFile, err := mergeConfigs(configs...)\n\t\tif err != nil {\n\t\t\treturn Config{}, fmt.Errorf(\"unable to merge config files: %w\", err)\n\t\t}\n\t\treturn mergedFile, nil","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/cmd/internal/config.go#L493-L529","documentation":"LoadAndMergeConfigs reads each file with os.ReadFile before parsing. This error wraps any OS-level read failure (ENOENT, EACCES, EISDIR, etc.) together with the file path, so the user knows which config file could not be read.","triggerScenarios":"os.ReadFile fails for one of the filePaths passed to LoadAndMergeConfigs: file does not exist, no read permission, or the path is a directory.","commonSituations":"Typos in the --config-file path; running the toolbox from a different working directory with a relative path; container images missing the mounted config file; wrong file permissions.","solutions":["Verify the file exists at the given path (ls / stat the path)","Use an absolute path or run from the correct working directory","Fix file permissions (chmod) or ensure the file is mounted/copied into the container"],"exampleFix":"// before\ntoolbox --config-file ./confg.yaml   # typo\n// after\ntoolbox --config-file ./config.yaml","handlingStrategy":"try-catch","validationCode":"for _, f := range filePaths {\n  if info, err := os.Stat(f); err != nil || info.IsDir() {\n    return fmt.Errorf(\"config file %q missing or is a directory\", f)\n  }\n}","typeGuard":null,"tryCatchPattern":"cfg, err := parser.LoadAndMergeConfigs(ctx, files)\nif err != nil {\n  var pe *fs.PathError\n  if errors.As(err, &pe) {\n    log.Printf(\"cannot read %s: %v\", pe.Path, pe.Err)\n  }\n  return err\n}","preventionTips":["Use absolute paths for config files","Verify file existence in startup scripts before launching the toolbox","Ensure config files are copied/mounted into containers"],"tags":["filesystem","io","config-loading"],"backgroundTag":"file-not-found","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"}