alibaba/open-code-review · error
resolve file %q: %w
Error message
resolve file %q: %w
What it means
This error wraps a failure from filepath.EvalSymlinks while resolving a workspace file path in FileReader.resolveWorkspacePath (internal/tool/filereader.go:110). The library calls EvalSymlinks to canonicalize the path so it can verify the real target stays inside the repository. A missing file is tolerated (returned as-is), but any other resolution failure — permission problems, symlink loops, or I/O errors on a path component — is wrapped as "resolve file %q: %w". It surfaces from FileReader.Read or FileReader.ReadLines in workspace mode.
Source
Thrown at internal/tool/filereader.go:110
}
func (fr *FileReader) resolveWorkspacePath(path string) (string, error) {
repoRoot, err := pathutil.CanonicalPath(fr.RepoDir)
if err != nil {
return "", fmt.Errorf("resolve repository path %q: %w", fr.RepoDir, err)
}
fullPath := filepath.Join(repoRoot, path)
if !pathutil.WithinBase(repoRoot, fullPath) {
return "", fmt.Errorf("file path %q is outside repository", path)
}
resolvedPath, err := filepath.EvalSymlinks(fullPath)
if err != nil {
if os.IsNotExist(err) {
return fullPath, nil
}
return "", fmt.Errorf("resolve file %q: %w", path, err)
}
if !pathutil.WithinBase(repoRoot, resolvedPath) {
return "", fmt.Errorf("file path %q is outside repository", path)
}
return resolvedPath, nil
}
func (fr *FileReader) readFromGitShow(parentCtx context.Context, path string) (string, error) {
ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second)
defer cancel()
args := []string{"-c", "core.quotepath=false", "show", "--end-of-options", fr.Ref + ":" + path}
if fr.Runner != nil {
output, err := fr.Runner.Output(ctx, fr.RepoDir, args...)
if err != nil {
return "", fmt.Errorf("git show %s:%s: %w", fr.Ref, path, err)
}
return string(output), nilView on GitHub (pinned to 5cf97d0d15)
Solutions
- Fix filesystem permissions so every component of the path from the repo root is traversable by the current user (chmod +x on directories).
- Inspect and repair symlink loops: run `find -L . -type l` or `namei -l <path>` to locate circular symlinks and remove them.
- Shorten or restructure overly deep paths if the error is ENAMETOOLONG.
- If the path is on a network/FUSE mount, retry after the mount is healthy, or read the file via git-show mode instead of workspace mode.
- Use errors.Unwrap / errors.Is (os.IsPermission, syscall.ELOOP) on the returned error to identify the exact cause before choosing a fix.
Example fix
// before: unreadable parent dir causes EvalSymlinks EACCES $ ls -ld /repo/secrets # drwx------ root root // after $ sudo chmod o+x /repo/secrets # allow traversal for the reader user
Defensive patterns
Strategy: try-catch
Validate before calling
info, err := os.Stat(filepath.Join(repoDir, path))
if err == nil {
if err := filepath.Walk(repoDir, func(p string, i os.FileInfo, e error) error { return nil }); err != nil { /* traversal issue possible */ }
}
// cheaper: resolve symlinks yourself first
resolved, err := filepath.EvalSymlinks(filepath.Join(repoDir, path))
if err != nil && !os.IsNotExist(err) { /* same failure will surface from the library */ } Type guard
func isSymlinkResolveErr(err error) bool {
var pe *os.PathError
if errors.As(err, &pe) {
return errors.Is(pe.Err, syscall.ELOOP) || errors.Is(pe.Err, os.ErrPermission) || errors.Is(pe.Err, syscall.ENAMETOOLONG)
}
return false
} Try / catch
resolved, err := fr.Read(ctx, path)
if err != nil {
if isSymlinkResolveErr(err) {
// fall back to git-show mode or skip the file
return fallbackRead(ctx, path)
}
return err
} Prevention
- Check out repositories on local filesystems, not FUSE/network mounts
- Audit symlinks in repos before review (find -L . -type l)
- Ensure the tool runs as a user with traverse (+x) rights on all parent directories
- Prefer ModeRange/ModeCommit (git show) when disk layout is unusual
When it happens
Trigger: Calling FileReader.Read/ReadLines in ModeWorkspace when EvalSymlinks fails with a non-ENOENT error: e.g. a directory component of the path is not readable (EACCES during resolution), the path contains a symlink loop (ELOOP), the path is too long (ENAMETOOLONG), or an I/O error occurs while walking a component. Purely nonexistent files do NOT trigger this — they return the unresolved full path instead.
Common situations: Repository checked out under a directory with restrictive permissions so path traversal fails mid-resolution; symlink chains pointing back at each other (common after bad manual linking or FUSE/network mounts); path components exceeding filesystem name limits; NFS or container volume mounts returning transient I/O errors.
Related errors
- resolve repo dir %s: %w
- resolve project rule %s: %w
- read background file %q: %w
- background file %q is a directory, not a file
- list sessions: %w
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/7f300162e119b885.
Report an issue: GitHub.