gastownhall/beads · error

checking destination sidecar %s: %w

Error message

checking destination sidecar %s: %w

What it means

This error wraps an underlying OS error returned by os.Stat while `bd migrate` checks whether a retire-operation's destination sidecar path already exists, during the pre-apply collision validation pass. It means the filesystem could not be queried at all for the destination path — not that the file exists or doesn't. The migration aborts safely before any changes are applied.

Source

Thrown at cmd/bd/migrate_hooks_apply.go:360

		return "#!/usr/bin/env sh\n"
	}

	return "#!/usr/bin/env sh\n" + trimmedLeading
}

func validateRetireCollisionPolicy(retireOps []hookMigrationRetireOp) error {
	for _, op := range retireOps {
		sourceExists, err := pathExists(op.SourcePath)
		if err != nil {
			return fmt.Errorf("checking source sidecar %s: %w", op.SourcePath, err)
		}
		if !sourceExists {
			continue
		}

		destinationExists, err := pathExists(op.DestinationPath)
		if err != nil {
			return fmt.Errorf("checking destination sidecar %s: %w", op.DestinationPath, err)
		}
		if !destinationExists {
			continue
		}

		equal, err := filesEqual(op.SourcePath, op.DestinationPath)
		if err != nil {
			return fmt.Errorf("comparing sidecars %s and %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,
			)
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error: run `ls -ld` on the destination path and each parent directory to find where access fails.
  2. Fix permissions on the destination directory (chown/chmod) or run the migration as a user with access.
  3. Remove or repair broken symlinks in the destination path.
  4. If the path is on a network/removable mount, remount it and re-run `bd migrate`.

Example fix

// before: destination under a root-owned dir
$ bd migrate
// after
$ sudo chown -R $(whoami) /usr/local/lib/bd/sidecars
$ bd migrate
Defensive patterns

Strategy: validation

Validate before calling

dest := op.DestinationPath
if _, err := os.Stat(filepath.Dir(dest)); err != nil {
	return fmt.Errorf("destination dir not accessible: %w", err)
}

Try / catch

if err := validateRetireCollisionPolicy(ops); err != nil {
	if pe, ok := err.(*fs.PathError); ok && errors.Is(pe, os.ErrPermission) {
		// fix permissions or re-run elevated
	}
	return err
}

Prevention

When it happens

Trigger: Running `bd migrate` hook application when os.Stat(op.DestinationPath) fails with an error other than os.ErrNotExist — e.g. a permission-denied directory on the destination path, a dangling symlink resolved through an inaccessible parent, or I/O error on the filesystem.

Common situations: Destination directory with restrictive permissions (different owner, read-only mount), destination path on a disconnected network mount, or a corrupted/broken symlink chain in the destination directory.

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/312ca510663c9f58. Report an issue: GitHub.