googleapis/mcp-toolbox · error

local path %q cannot be resolved for source %q: %w

Error message

local path %q cannot be resolved for source %q: %w

What it means

validateLocalPath could not resolve symbolic links along the local path when checking it against the source's allowed local roots. The wrapped OS error (from ResolveSymlinks, typically *PathError with ENOENT/EACCES/ELOOP) tells the real reason. The path passed the name-level match but symlink resolution failed, so access is denied conservatively.

Source

Thrown at internal/sources/cloudstorage/cloudstorage.go:138

	}
	if len(s.AllowedLocalRoots) == 0 {
		return nil
	}

	nameMatched := false
	for _, root := range s.AllowedLocalRoots {
		if isUnderRoot(clean, root) {
			nameMatched = true
			break
		}
	}
	if !nameMatched {
		return fmt.Errorf("local path %q is not under any allowed local roots for source %q", p, s.Name)
	}

	resolved, err := cloudstoragecommon.ResolveSymlinks(clean)
	if err != nil {
		return fmt.Errorf("local path %q cannot be resolved for source %q: %w", p, s.Name, err)
	}
	for _, root := range s.AllowedLocalRoots {
		// A root we cannot resolve authorizes nothing; skip it rather than
		// falling back to the name-level match we already passed.
		resolvedRoot, err := cloudstoragecommon.ResolveSymlinks(root)
		if err != nil {
			continue
		}
		if isUnderRoot(resolved, resolvedRoot) {
			return nil
		}
	}
	return fmt.Errorf("local path %q resolves through a symbolic link to a target outside the allowed local roots for source %q", p, s.Name)
}

func isUnderRoot(target, root string) bool {
	target = filepath.Clean(target)
	root = filepath.Clean(root)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check the wrapped %w error: create missing directories (os.MkdirAll) or fix the path typo before calling DownloadObject/UploadObject.
  2. Fix filesystem permissions so the process user can traverse every path component.
  3. Remove or repair the symlink loop or dangling symlink (readlink -f <path> to reproduce).
  4. If the root itself is unresolvable, correct the allowed_local_roots configuration to point at existing real directories.

Example fix

// before
err := source.UploadObject(ctx, "bkt", "obj", "/data/out/missing/file.bin")
// after
if err := os.MkdirAll("/data/out", 0o755); err != nil { return err }
err := source.UploadObject(ctx, "bkt", "obj", "/data/out/file.bin")
Defensive patterns

Strategy: validation

Validate before calling

p := "/data/out/file.bin"
if _, err := filepath.EvalSymlinks(p); err != nil {
    return fmt.Errorf("path not resolvable: %w", err)
}

Try / catch

var pathErr *fs.PathError
if errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.ENOENT) {
    // create missing dirs / fix path
}

Prevention

When it happens

Trigger: Calling DownloadObject or UploadObject (which invoke validateLocalPath) with a local path whose symlinks cannot be resolved: the path (or an ancestor) does not exist, the process lacks search permission on a directory component, or a symlink loop (ELOOP, >40 levels) exists.

Common situations: Typoed or not-yet-created download destination; downloading into a directory removed at runtime; running the server as a user without execute permission on a parent directory (e.g. /root/...); a dangling symlink created by another process; broken symlink chain in a container with a stale volume mount.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/fbcc075eaf6416ad. Report an issue: GitHub.