{"record":{"id":"7193880ad827a383","repo":"matryer/xbar","slug":"write-plugin-file-s","errorCode":null,"errorMessage":"write plugin file %s","messagePattern":"write plugin file (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/install.go","lineNumber":126,"sourceCode":"\t\treturn errors.New(\"no plugin files\")\n\t}\n\tif len(plugin.Files) > 1 {\n\t\treturn errors.Errorf(\"only one plugin file supported: found %d.\", len(plugin.Files))\n\t}\n\tfor _, f := range plugin.Files {\n\t\tpluginFile := dstPath\n\t\tdir := path.Dir(pluginFile)\n\t\tif err := os.MkdirAll(dir, 0777); err != nil {\n\t\t\treturn errors.Wrapf(err, \"create directory %s for plugin\", dir)\n\t\t}\n\t\twriter, err := os.Create(pluginFile)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"create plugin file %s\", f.Path)\n\t\t}\n\t\tdefer writer.Close()\n\t\treader := strings.NewReader(f.Content)\n\t\tif _, err := io.Copy(writer, reader); err != nil {\n\t\t\treturn errors.Wrapf(err, \"write plugin file %s\", f.Path)\n\t\t}\n\t\t// If the Filename property of the current file matches the Filename\n\t\t// property of the plugin, this is the entry point, so set it to be\n\t\t// executable.\n\t\tif f.Filename != plugin.Filename {\n\t\t\tcontinue\n\t\t}\n\t\tif err := os.Chmod(pluginFile, 0755); err != nil {\n\t\t\treturn errors.Wrap(err, \"set executable permission on plugin entry point\")\n\t\t}\n\t\t// write the default variables\n\t\tplugin, err := metadata.Parse(metadata.DebugfNoop, pluginFile, f.Content)\n\t\tif err != nil {\n\t\t\tlog.Println(\"install plugin: unable to parse metadata:\", err)\n\t\t}\n\t\tif len(plugin.Vars) > 0 {\n\t\t\tdefaultVars := make(map[string]interface{})\n\t\t\tfor _, pluginVar := range plugin.Vars {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/install.go#L108-L144","documentation":"Returned by writePluginFiles when io.Copy fails while streaming the plugin file content from memory into the newly created file on disk. It wraps the write error with the plugin file path. On most local filesystems this is rare and points to an I/O-level problem (disk full, device error) or an issue with the writer being closed/unusable.","triggerScenarios":"Installer.Install -> writePluginFiles when the io.Copy(writer, strings.NewReader(f.Content)) write fails: no space left on device, I/O error on the underlying filesystem, or the file handle became invalid after os.Create.","commonSituations":"Disk filling up mid-install; failing hardware or network filesystem (NFS) drop; extremely large plugin content exceeding quota between create and write.","solutions":["Free disk space or increase quota (df -h, check du of the plugin dir).","Check filesystem health (dmesg / smartctl) if errors persist.","Retry the install after confirming the volume is writable."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if st, err := os.Stat(filepath.Dir(dstPath)); err != nil || !st.IsDir() {\n    return fmt.Errorf(\"plugin dir not ready\")\n}\n// also check free space via syscall.Statfs when on Linux","typeGuard":null,"tryCatchPattern":"err := installer.Install(plugin)\nvar pe *os.PathError\nif errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {\n    log.Fatalf(\"disk full while writing plugin file: %s\", pe.Path)\n}\nreturn err","preventionTips":["Monitor free disk space on the volume hosting PluginDir.","Avoid installing plugins on flaky network filesystems.","Retry installs idempotently — writePluginFiles overwrites on retry.","Keep plugin file content sizes reasonable."],"tags":["go","filesystem","io","plugin-install"],"backgroundTag":"no-space-left-on-device","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}