gastownhall/beads · error
checking sidecar destination %s: %w
Error message
checking sidecar destination %s: %w
What it means
This wraps an os.Stat failure on the retire op's destination path during retirement (after the source was confirmed to exist). Any stat error other than a clean not-exist aborts the retire step. Because this happens during apply, it can leave the migration partially applied.
Source
Thrown at cmd/bd/migrate_hooks_apply.go:393
)
}
}
return nil
}
func retireHookSidecar(op hookMigrationRetireOp) (string, error) {
sourceExists, err := pathExists(op.SourcePath)
if err != nil {
return "", fmt.Errorf("checking sidecar %s: %w", op.SourcePath, err)
}
if !sourceExists {
return "", nil
}
destinationExists, err := pathExists(op.DestinationPath)
if err != nil {
return "", fmt.Errorf("checking sidecar destination %s: %w", op.DestinationPath, err)
}
if destinationExists {
equal, err := filesEqual(op.SourcePath, op.DestinationPath)
if err != nil {
return "", fmt.Errorf("comparing sidecar %s to %s: %w", op.SourcePath, op.DestinationPath, err)
}
if !equal {
return "", fmt.Errorf("artifact collision for %s: %s already exists with different content", op.SourcePath, op.DestinationPath)
}
if err := os.Remove(op.SourcePath); err != nil {
return "", fmt.Errorf("removing already-retired sidecar %s: %w", op.SourcePath, err)
}
return op.SourcePath + " -> " + op.DestinationPath + " (destination already existed)", nil
}
if err := os.Rename(op.SourcePath, op.DestinationPath); err != nil {
return "", fmt.Errorf("retiring sidecar %s -> %s: %w", op.SourcePath, op.DestinationPath, err)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error; run `ls -ld` on the destination path and its parents to find the failure point.
- Fix directory permissions or remount the volume holding the destination.
- Re-run `bd migrate`; retire ops skip sources that no longer exist, so retries are safe.
Example fix
// before $ bd migrate checking sidecar destination /mnt/ext/bd/x.sh: input/output error // after $ sudo mount /mnt/ext && bd migrate
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(filepath.Dir(op.DestinationPath)); err != nil {
return fmt.Errorf("destination dir not accessible: %w", err)
} Try / catch
if _, err := retireHookSidecar(op); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && !errors.Is(pe.Err, os.ErrNotExist) {
return fmt.Errorf("destination sidecar %s unusable: %w", pe.Path, pe.Err)
}
return err
} Prevention
- Confirm the destination volume is mounted before migrating
- Pre-create the destination directory with permissive-enough mode
- Avoid switching uid (sudo) between preview and apply
When it happens
Trigger: During `bd migrate` apply, destinationExists check fails: destination parent directory permission-denied, destination on an unmounted volume, or an I/O error from the filesystem.
Common situations: Destination directory created with restrictive mode by an earlier run; external drive/NFS share disconnected between validation and apply; user switched effective uid via sudo mid-session.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- checking destination sidecar %s: %w
- checking sidecar %s: %w
- removing already-retired sidecar %s: %w
- dolt path is not executable
- failed to create backup directory: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d85b96ccc90f3937.
Report an issue: GitHub.