{"record":{"id":"e137f0e70b25e1d7","repo":"sipeed/picoclaw","slug":"close-destination-file-s-w","errorCode":null,"errorMessage":"close destination file %s: %w","messagePattern":"close destination file (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/skills/helpers.go","lineNumber":356,"sourceCode":"\n\t\tif info.IsDir() {\n\t\t\treturn os.MkdirAll(dstPath, info.Mode())\n\t\t}\n\n\t\tsrcFile, err := os.Open(path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer srcFile.Close()\n\n\t\tdstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t_, copyErr := io.Copy(dstFile, srcFile)\n\t\tif closeErr := dstFile.Close(); closeErr != nil && copyErr == nil {\n\t\t\treturn fmt.Errorf(\"close destination file %s: %w\", dstPath, closeErr)\n\t\t}\n\t\treturn copyErr\n\t})\n}\n","sourceCodeStart":338,"sourceCodeEnd":361,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/skills/helpers.go#L338-L361","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped errno: ENOSPC -> free disk space; EIO -> inspect device/dmesg; EACCES -> fix permissions on destination","Exclude the workspace skills directory from sync/antivirus real-time scanning and retry the install","Verify destination filesystem health (remount, fsck) if EIO repeats","Retry the builtin install after remediation; partially copied dirs are truncated by O_TRUNC on rerun"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"func diskAvailable(path string, need uint64) bool {\n    var st syscall.Statfs_t\n    if err := syscall.Statfs(path, &st); err != nil { return false }\n    return uint64(st.Bavail)*uint64(st.Bsize) > need\n}","typeGuard":null,"tryCatchPattern":"err := copyDirectory(src, dst)\nif err != nil {\n    var pathErr *os.PathError\n    if errors.As(err, &pathErr) && pathErr.Op == \"close\" {\n        // treat copy as incomplete: remove partial dst and retry or report low-disk\n    }\n}","preventionTips":["Check free disk space before installing builtin skills","Exclude workspace skills dirs from sync clients and real-time antivirus scans","Treat any close error as a failed copy: clean up partial destinations"],"tags":["filesystem","io","skills","disk-full"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}