{"record":{"id":"71bca358c6970d11","repo":"matryer/xbar","slug":"create-plugin-file-s","errorCode":null,"errorMessage":"create plugin file %s","messagePattern":"create plugin file (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/install.go","lineNumber":121,"sourceCode":"// writePluginFiles iterates through the files defined for the plugin, and\n// writes them to the plugin installation directory, and sets the entry point\n// to be executable.\nfunc (i Installer) writePluginFiles(dstPath string, plugin metadata.Plugin) error {\n\tif len(plugin.Files) == 0 {\n\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 {","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/install.go#L103-L139","documentation":"Returned by writePluginFiles when os.Create cannot create the plugin file at dstPath after its directory was successfully created. It wraps the OS error with the file path. Typical causes are permission denied on the newly created directory, quota, or the destination path being a directory.","triggerScenarios":"Installer.Install -> writePluginFiles when os.Create(dstPath) fails: directory permissions (0777 masked by umask may still be insufficient if parent changed), dstPath already exists as a directory, disk full, or SELinux/AppArmor denial.","commonSituations":"Disk quota exceeded in home directory; anti-virus or security policy blocking new executable files; dstPath collides with an existing directory; installing on a full disk.","solutions":["Check disk space/quota (df -h) and free space if the disk is full.","Verify dstPath is not an existing directory and remove/replace it.","Check effective permissions/umask and SELinux/AppArmor denials (audit log) on the plugin directory.","Retry Install after fixing permissions on the plugin directory."],"exampleFix":"// before (dstPath is a directory)\nos.MkdirAll(dstPath, 0755)\ninstaller.Install(plugin)\n// after\nif info, err := os.Stat(dstPath); err == nil && info.IsDir() {\n    os.RemoveAll(dstPath)\n}\ninstaller.Install(plugin)","handlingStrategy":"validation","validationCode":"func ensureCreateOK(path string) error {\n    if fi, err := os.Stat(path); err == nil && fi.IsDir() {\n        return fmt.Errorf(\"%s is a directory\", path)\n    }\n    dir := filepath.Dir(path)\n    f, err := os.CreateTemp(dir, \".create-test\")\n    if err != nil { return err }\n    f.Close(); os.Remove(f.Name())\n    return nil\n}\n// run before Install","typeGuard":null,"tryCatchPattern":"err := installer.Install(plugin)\nif err != nil && strings.Contains(err.Error(), \"create plugin file\") {\n    var pe *os.PathError\n    if errors.As(err, &pe) {\n        switch {\n        case os.IsPermission(pe): log.Fatalf(\"permission denied: %s\", pe.Path)\n        default: log.Fatalf(\"cannot create %s: %v\", pe.Path, pe.Err)\n        }\n    }\n    return err\n}","preventionTips":["Check disk space and quota before installing.","Ensure dstPath does not collide with an existing directory.","Verify umask/SELinux policy allows creating executable files in the plugin dir.","Use a user-owned plugin directory."],"tags":["go","filesystem","permissions","plugin-install"],"backgroundTag":"file-create-failed","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}