{"record":{"id":"08fcf36208017ae7","repo":"larksuite/cli","slug":"copy-tar-entry-w-close-file-w","errorCode":null,"errorMessage":"copy tar entry: %w; close file: %w","messagePattern":"copy tar entry: %w; close file: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/apps/plugin_common.go","lineNumber":401,"sourceCode":"\n\t\tswitch hdr.Typeflag {\n\t\tcase tar.TypeSymlink, tar.TypeLink:\n\t\t\tcontinue\n\t\tcase tar.TypeDir:\n\t\t\tif err := os.MkdirAll(target, 0o755); err != nil { //nolint:forbidigo // shortcuts cannot import internal/vfs; tgz extraction.\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase tar.TypeReg:\n\t\t\tif err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil { //nolint:forbidigo\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tf, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(hdr.Mode)&0o755) //nolint:forbidigo\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif _, err := io.Copy(f, io.LimitReader(tr, pluginExtractMaxBytes)); err != nil {\n\t\t\t\tif cerr := f.Close(); cerr != nil {\n\t\t\t\t\treturn fmt.Errorf(\"copy tar entry: %w; close file: %w\", err, cerr) //nolint:forbidigo // intermediate helper error; callers wrap as typed\n\t\t\t\t}\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := f.Close(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// pluginStripFirstComponent removes the first path component (\"package/foo\" → \"foo\").\nfunc pluginStripFirstComponent(name string) string {\n\tname = filepath.ToSlash(name)\n\tif i := strings.Index(name, \"/\"); i >= 0 {\n\t\treturn name[i+1:]\n\t}\n\treturn \"\"","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/apps/plugin_common.go#L383-L419","documentation":"During extraction, io.Copy from the tar entry to the created file failed and closing the partially written file also failed; both errors are joined as 'copy tar entry: %w; close file: %w'. This usually means the disk filled up (or a quota/I/O error) mid-extraction, and the close error compounds it.","triggerScenarios":"Extracting a plugin whose entry exceeds available disk space or hits an I/O error while the target file cannot be closed cleanly (fd exhaustion, filesystem error).","commonSituations":"Small containers/VMs with tight disk limits installing large plugins, or full temp volumes during pluginInstallOne/pluginInstallLocal.","solutions":["Free disk space in the destination volume and retry the install","Check filesystem health/quotas on the destination directory's volume","If persistent, extract to a different destination directory with more space"],"exampleFix":"// before\n$ df -h /root/.lark-cli/plugins  ->  100% used\n// after\n$ docker system prune  # or otherwise free space, then retry\nlark-cli plugin install --file plugin.tgz","handlingStrategy":"retry","validationCode":"// ensure free space in the destination volume before installing\n// df -h <destDir>  (require headroom larger than the archive's extracted size)","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"copy tar entry\") {\n\t// free disk space / check volume health, then retry the install\n}","preventionTips":["Monitor free space on the volume hosting the plugin directory","Clean old plugin versions and caches before large installs","Check container/volume disk limits when installing large plugins"],"tags":["filesystem","disk-full","plugin-install"],"backgroundTag":"no-space-left-on-device","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}