dagger/dagger · error
failed to resolve target path %s: %w
Error message
failed to resolve target path %s: %w
What it means
copyFile calls c.destPathResolver(target) to map the destination path to its real (host) path before os.Link. A resolver failure is wrapped as "failed to resolve target path %s". Like the source resolver error, it indicates the destination could not be mapped to a real path the linker can use.
Source
Thrown at internal/fsutil/copy/copy_linux.go:93
switch {
case err == nil:
// destination already exists, remove it
if removeErr := os.Remove(target); removeErr != nil {
return false, fmt.Errorf("failed to remove existing destination file %s: %w", target, removeErr)
}
case errors.Is(err, os.ErrNotExist):
// destination does not exist, proceed
default:
return false, fmt.Errorf("failed to stat destination file %s: %w", target, err)
}
realSource, err := c.sourcePathResolver(source)
if err != nil {
return false, fmt.Errorf("failed to resolve source path %s: %w", source, err)
}
realTarget, err := c.destPathResolver(target)
if err != nil {
return false, fmt.Errorf("failed to resolve target path %s: %w", target, err)
}
err = os.Link(realSource, realTarget)
switch {
case err == nil:
return true, nil
case errors.Is(err, unix.EXDEV), errors.Is(err, syscall.EMLINK):
// either crossing filesystem boundary or too many links, fallback to copy
slog.ExtraDebug("hardlink failed, falling back to copy", "source", source, "target", target, "error", err)
default:
return false, fmt.Errorf("failed to create hardlink from %s to %s: %w", source, target, err)
}
}
src, err := os.Open(source)
if err != nil {
return false, errors.Wrapf(err, "failed to open source %s", source)
}View on GitHub (pinned to 82ba2681db)
Solutions
- Ensure the destination path is inside the configured destination root.
- Clean the target path (filepath.Clean / avoid "..") so it stays within the destination root.
- Fix or correctly configure the destPathResolver for the actual destination layout.
- Disable the hardlink optimization to bypass path resolution entirely (plain copy is used instead).
Example fix
// before: target escapes the dest root via .. target := filepath.Join(destRoot, "../escape", name) // after target := filepath.Join(destRoot, filepath.Clean(name))
Defensive patterns
Strategy: validation
Validate before calling
func withinRoot(root, p string) bool {
rel, err := filepath.Rel(root, p)
return err == nil && rel != ".." && !strings.HasPrefix(rel, ".."+string(filepath.Separator))
}
// call before copy:
if !withinRoot(destRoot, targetPath) {
return fmt.Errorf("target %s escapes destination root", targetPath)
} Try / catch
if err := copier.Copy(ctx, src, dst); err != nil && strings.Contains(err.Error(), "failed to resolve target path") {
// clean/rebase the target path inside destRoot and retry
} Prevention
- filepath.Clean destination paths and strip ".." components
- Avoid symlinked directories in destination paths that escape the root
- Configure the copier's dest root to match actual layout
When it happens
Trigger: destPathResolver returns an error — the target path is outside the configured destination root, the path traverses symlinks that escape it, or the custom resolver callback rejects the path.
Common situations: Destination path includes a symlinked directory resolving outside the copy root; programmatically-built target strings with ".." components escaping the root; resolver misconfigured with the wrong root prefix.
Related errors
- failed to resolve source path %s: %w
- failed to create hardlink from %s to %s: %w
- failed to resolve symlinks in %s
- failed to hardlink during apply
- failed to chmod %s
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/ffef43c4a1ef3471.
Report an issue: GitHub.