docker/compose · error
deleting paths in %s: %w
Error message
deleting paths in %s: %w
What it means
During Tar.Sync, when some host paths no longer exist, compose builds an 'rm -rf <paths>' command and execs it in each matching container via LowLevelClient.Exec before copying. If that exec fails for a container (non-zero exit, exec API failure, container restarting/paused), the error is collected (not fail-fast) and joined into the sync result. The %s names the offending container ID.
Source
Thrown at internal/sync/tar.go:105
deleteCmd = append([]string{"rm", "-rf"}, pathsToDelete...)
}
var (
eg errgroup.Group
errMu sync.Mutex
errs = make([]error, 0, len(containers)*2) // max 2 errs per container
)
eg.SetLimit(16) // arbitrary limit, adjust to taste :D
for i := range containers {
containerID := containers[i].ID
tarReader := tarArchive(pathsToCopy)
eg.Go(func() error {
if len(deleteCmd) != 0 {
if err := t.client.Exec(ctx, containerID, deleteCmd, nil); err != nil {
errMu.Lock()
errs = append(errs, fmt.Errorf("deleting paths in %s: %w", containerID, err))
errMu.Unlock()
}
}
if err := t.client.Untar(ctx, containerID, tarReader); err != nil {
errMu.Lock()
errs = append(errs, fmt.Errorf("copying files to %s: %w", containerID, err))
errMu.Unlock()
}
return nil // don't fail-fast; collect all errors
})
}
_ = eg.Wait()
return errors.Join(errs...)
}
type ArchiveBuilder struct {View on GitHub (pinned to ddc4b044b6)
Solutions
- docker inspect <containerID> to check State (Paused/Restarting) and unpause or wait for it: docker unpause <id> or docker compose restart <service>
- If the image is distroless/scratch, add rm (busybox) or avoid deletions in sync paths since exec rm -rf cannot work there
- Check dockerd logs for exec API errors; restart the container if its exec channel is wedged
- If deletions are not needed, ensure host paths in the mapping still exist so deleteCmd stays empty
Defensive patterns
Strategy: try-catch
Validate before calling
// only pass delete-mappings when containers can exec rm
if len(deletedPaths) > 0 {
for _, c := range containers {
st, _ := client.ContainerInspect(ctx, c.ID)
if st.State == nil || st.State.Paused || st.State.Restarting { skipOrWait(c.ID) }
}
} Try / catch
// Sync joins per-container errors; split with errors.Unwrap on the joined tree and match the 'deleting paths in <id>' prefix to target one container
for _, e := range errors.Unwrap(syncErr).([]error) { /* handle per container ID */ } Prevention
- Do not rely on deletion sync with distroless/scratch images
- Keep synced containers running and unpaused during watch
- Treat delete failures as retriable: rerun the sync after stabilizing the container
When it happens
Trigger: Tar.Sync with at least one deleted host path (len(pathsToDelete) != 0) against a container that cannot run exec: container is paused, restarting, its runtime exec API errors, or 'rm' is absent/not executable in the image (distroless/scratch).
Common situations: Syncing deletions to minimal images without coreutils, containers mid-restart during 'docker compose watch', or a stopped-but-listed replica whose exec channel is closed.
Related errors
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/5c44bc8cec11e768.
Report an issue: GitHub.