sipeed/picoclaw · error

close destination file %s: %w

Error message

close destination file %s: %w

What it means

Raised by copyDirectory (used by builtin skill installation) while walking the source tree: io.Copy to the destination file succeeded, but the subsequent dstFile.Close() failed. Closing a written file is where buffered data is flushed and final metadata committed, so a close failure usually means the copy is actually incomplete even though io.Copy reported no error.

Source

Thrown at cmd/picoclaw/internal/skills/helpers.go:356

		if info.IsDir() {
			return os.MkdirAll(dstPath, info.Mode())
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode())
		if err != nil {
			return err
		}

		_, copyErr := io.Copy(dstFile, srcFile)
		if closeErr := dstFile.Close(); closeErr != nil && copyErr == nil {
			return fmt.Errorf("close destination file %s: %w", dstPath, closeErr)
		}
		return copyErr
	})
}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Check the wrapped errno: ENOSPC -> free disk space; EIO -> inspect device/dmesg; EACCES -> fix permissions on destination
  2. Exclude the workspace skills directory from sync/antivirus real-time scanning and retry the install
  3. Verify destination filesystem health (remount, fsck) if EIO repeats
  4. Retry the builtin install after remediation; partially copied dirs are truncated by O_TRUNC on rerun
Defensive patterns

Strategy: fallback

Validate before calling

func diskAvailable(path string, need uint64) bool {
    var st syscall.Statfs_t
    if err := syscall.Statfs(path, &st); err != nil { return false }
    return uint64(st.Bavail)*uint64(st.Bsize) > need
}

Try / catch

err := copyDirectory(src, dst)
if err != nil {
    var pathErr *os.PathError
    if errors.As(err, &pathErr) && pathErr.Op == "close" {
        // treat copy as incomplete: remove partial dst and retry or report low-disk
    }
}

Prevention

When it happens

Trigger: Disk fills up exactly at flush time (ENOSPC on close), I/O error on the destination device, or an external program (antivirus, sync client) truncating/locking the destination between write and close. Occurs during `picoclaw skills install --builtin`-style copying of ./picoclaw/skills/<name> into the workspace.

Common situations: Small or nearly-full disk on the workspace volume; workspace inside a cloud-sync folder where the sync engine interferes; flaky USB/network mount; destination on a filesystem enforcing quotas.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/e137f0e70b25e1d7. Report an issue: GitHub.