{"record":{"id":"6114263b4ad07e60","repo":"matryer/xbar","slug":"create-directory-s-for-plugin","errorCode":null,"errorMessage":"create directory %s for plugin","messagePattern":"create directory (.+?) for plugin","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/install.go","lineNumber":117,"sourceCode":"\t}\n\treturn candidatePath, nil\n}\n\n// 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\")","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/install.go#L99-L135","documentation":"Returned by writePluginFiles when os.MkdirAll fails to create the parent directory of the destination plugin file during installation. It wraps the underlying OS error with the target directory path, so the cause is typically a filesystem permission problem or an invalid/occupied path. The library creates the directory with 0777 (before umask) before writing the plugin file into it.","triggerScenarios":"Calling Installer.Install (via writePluginFiles) when the parent directory of dstPath cannot be created: no write permission on an ancestor directory, a path component is an existing regular file, pluginDir points to read-only media, or the path is too long.","commonSituations":"Installing plugins into a system-wide directory as a non-root user; a stale regular file occupies part of the path; read-only container filesystem or Docker volume; PluginDir configured with a typo making an illegal path.","solutions":["Check and fix permissions on the parent directory (chown/chmod or run as a user with write access).","Verify PluginDir/dstPath is correct and no file occupies a path component (ls the intermediate path).","Ensure the filesystem is writable (not read-only mount) and path length is within limits.","Pre-create the plugin directory manually with mkdir -p and correct ownership, then retry Install."],"exampleFix":"// before (fails: ~/.upterm/plugins owned by root)\ninstaller.Install(plugin)\n// after\nerr := exec.Command(\"sudo\", \"chown\", os.Getuid(), pluginDir).Run()\nif err != nil { log.Fatal(err) }\nerr = installer.Install(plugin)","handlingStrategy":"validation","validationCode":"func canWriteDir(dir string) error {\n    for p := dir; ; p = filepath.Dir(p) {\n        if _, err := os.Stat(p); err == nil {\n            f, err := os.CreateTemp(p, \".write-test\")\n            if err != nil { return err }\n            f.Close(); os.Remove(f.Name())\n            return nil\n        } else if !os.IsNotExist(err) {\n            return err\n        }\n        if p == \"/\" { return os.ErrPermission }\n    }\n}\n// call: if err := canWriteDir(filepath.Dir(dstPath)); err != nil { return err }","typeGuard":null,"tryCatchPattern":"err := installer.Install(plugin)\nif err != nil {\n    if strings.Contains(err.Error(), \"create directory\") {\n        var pe *os.PathError\n        if errors.As(err, &pe) && os.IsPermission(pe) {\n            log.Fatalf(\"no permission to create %s: %v\", pe.Path, pe.Err)\n        }\n    }\n    return err\n}","preventionTips":["Ensure the process user owns or has write access to the plugin directory's parent.","Never point PluginDir at read-only or system-managed paths.","Pre-create the plugin directory at startup with correct permissions.","Avoid paths where an intermediate component could be a regular file."],"tags":["go","filesystem","permissions","plugin-install"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}