dagger/dagger · error
invalid remove path %q: absolute paths are not allowed
Error message
invalid remove path %q: absolute paths are not allowed
What it means
safeLocalExportRemovePath rejects remove paths that are absolute (or carry a Windows volume name) during local export diff sync. This is a path-traversal guard: deletes are only allowed for paths relative to the export root. The remote sync diff sent an absolute path, which the client refuses.
Source
Thrown at engine/client/filesync.go:345
}
for {
msg := filesync.BytesMessage{}
if err := stream.RecvMsg(&msg); err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
if _, err := destF.Write(msg.Data); err != nil {
return err
}
}
}
func safeLocalExportRemovePath(absRoot, removePath string) (string, error) {
if filepath.IsAbs(removePath) || filepath.VolumeName(removePath) != "" {
return "", fmt.Errorf("invalid remove path %q: absolute paths are not allowed", removePath)
}
if strings.Contains(removePath, `\`) {
return "", fmt.Errorf("invalid remove path %q: backslashes are not allowed in diff paths", removePath)
}
cleanRel := path.Clean(strings.TrimSuffix(removePath, "/"))
if cleanRel == "." || cleanRel == ".." || strings.HasPrefix(cleanRel, "../") {
return "", fmt.Errorf("invalid remove path %q: escapes export root", removePath)
}
target := filepath.Join(absRoot, filepath.FromSlash(cleanRel))
rel, err := filepath.Rel(absRoot, target)
if err != nil {
return "", fmt.Errorf("validate remove path %q: %w", removePath, err)
}
if rel == "." || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) || filepath.IsAbs(rel) {
return "", fmt.Errorf("invalid remove path %q: escapes export root", removePath)
}View on GitHub (pinned to 82ba2681db)
Solutions
- Ensure the sync engine emits delete paths relative to the session root.
- Strip the leading root prefix from paths before issuing remove operations.
- Update the client/engine pair to matching versions so diff-path conventions agree.
Example fix
// before removePath := "/home/dev/project/file.txt" // after: make it relative to the export root removePath = strings.TrimPrefix(removePath, root+"/")
Defensive patterns
Strategy: validation
Validate before calling
func isSafeRemovePath(p string) bool {
return !filepath.IsAbs(p) && filepath.VolumeName(p) == ""
} Try / catch
if _, err := safeLocalExportRemovePath(root, p); err != nil {
log.Printf("skipping unsafe remove %q: %v", p, err)
return nil // or convert to a relative path and retry
} Prevention
- Always emit diff remove paths relative to the session root.
- Never construct remove paths by joining the root client-side.
- Strip the root prefix on the sender before sending deletes.
When it happens
Trigger: A filesync remove/delete operation carries a removePath like "/etc/passwd" or "C:\\tmp\\f" (VolumeName non-empty) into safeLocalExportRemovePath via DiffCopy.
Common situations: A buggy or malicious remote engine sends absolute delete paths; a sync root configured with absolute-style diff paths; cross-OS sync where Windows drive letters leak into paths.
Related errors
- invalid remove path %q: escapes export root
- path cannot escape directory: %s
- git module source subpath points out of root: %q
- path cannot escape search root: %s
- path %q resolves outside root %q
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/614e6c57748a0522.
Report an issue: GitHub.