googleapis/mcp-toolbox · error
error reading config folder %w
Error message
error reading config folder %w
What it means
`scanWatchedFiles` throws "error reading config folder %w" when `os.ReadDir(folderToWatch)` fails while scanning the watched config directory for changed .yaml/.yml files during dynamic reload. This is a filesystem-level failure — the folder could not be listed at all — and wraps the underlying os error (which names the reason: not found, permission denied, etc.). The caller `watchChanges` receives the error and can no longer detect config changes.
Source
Thrown at cmd/root.go:199
}
// Helper to check if a file has a newer ModTime than stored in the map
func checkModTime(path string, mTime time.Time, lastSeen map[string]time.Time) bool {
if mTime.After(lastSeen[path]) {
lastSeen[path] = mTime
return true
}
return false
}
// Helper to scan watched files and check their modification times in polling system
func scanWatchedFiles(watchingFolder bool, folderToWatch string, watchedFiles map[string]bool, lastSeen map[string]time.Time) (map[string]bool, bool, error) {
changed := false
currentDiskFiles := make(map[string]bool)
if watchingFolder {
files, err := os.ReadDir(folderToWatch)
if err != nil {
return nil, changed, fmt.Errorf("error reading config folder %w", err)
}
for _, f := range files {
if !f.IsDir() && (strings.HasSuffix(f.Name(), ".yaml") || strings.HasSuffix(f.Name(), ".yml")) {
fullPath := filepath.Join(folderToWatch, f.Name())
currentDiskFiles[fullPath] = true
if info, err := f.Info(); err == nil {
if checkModTime(fullPath, info.ModTime(), lastSeen) {
changed = true
}
}
}
}
} else {
for f := range watchedFiles {
if info, err := os.Stat(f); err == nil {
currentDiskFiles[f] = true
if checkModTime(f, info.ModTime(), lastSeen) {
changed = trueView on GitHub (pinned to 8cc6e09de2)
Solutions
- Read the wrapped OS error — it states whether the path is missing, permission-denied, or not a directory
- Verify `folderToWatch` exists and is a directory: `ls -la <folder>`
- Restore read permission on the folder for the toolbox process user (`chmod/chown`)
- If the folder was deleted/moved, recreate it or restart the server pointing at the correct path
- For containers, ensure the config volume mount is present and not read-removed at runtime
Example fix
// before: server started watching a folder that was later renamed toolbox serve --config-folder ./configs // ./configs deleted at runtime // after: recreate the folder or restart against the right path mkdir -p ./configs && toolbox serve --config-folder ./configs
Defensive patterns
Strategy: validation
Validate before calling
// Check the watch folder exists and is readable before starting the server
func watchable(dir string) error {
info, err := os.Stat(dir)
if err != nil { return err }
if !info.IsDir() { return fmt.Errorf("%s is not a directory", dir) }
f, err := os.Open(dir)
if err != nil { return err }
return f.Close()
} Try / catch
files, err := os.ReadDir(folderToWatch)
if err != nil {
return nil, changed, fmt.Errorf("error reading config folder %w", err)
} Prevention
- Confirm the config folder exists, is a directory, and is readable before enabling watch mode
- Don't delete/rename the watched folder at runtime; recreate it if needed and re-save a file to re-trigger scanning
- In containers, verify the config volume stays mounted for the server's lifetime
- Keep folder permissions stable (avoid chmod/chown changes while watching)
When it happens
Trigger: `toolbox serve` is run with folder watching enabled (watching a directory rather than a single file) and the directory was deleted, renamed, is on an unmounted volume, or the process lacks read permission on it; `scanWatchedFiles` is invoked on each watch tick.
Common situations: Config directory moved/deleted while the server runs; running in a container where the config dir mount disappeared; permission changes (chmod/chown) after startup; pointing `--watch-folder` (or equivalent) at a path that doesn't exist.
Related errors
- unable to validate reloaded edits: %w
- error finding YAML files in %q: %w
- error finding YML files in %q: %w
- failed to stat file: %w
- failed to rename file: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/09103cf874d8a252.
Report an issue: GitHub.