{"record":{"id":"629cb4fff035058d","repo":"matryer/xbar","slug":"read-plugin-source","errorCode":null,"errorMessage":"read plugin source","messagePattern":"read plugin source","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/variables.go","lineNumber":130,"sourceCode":"\t\treturn nil, err\n\t}\n\tvar vars map[string]interface{}\n\tif err := json.Unmarshal(b, &vars); err != nil {\n\t\treturn nil, errors.Wrap(err, \"json.Unmarshal\")\n\t}\n\treturn vars, nil\n}\n\nfunc (p *Plugin) loadVariablesFromPluginMetadata() (map[string]interface{}, error) {\n\t// read the plugin metadata for default values\n\tpluginFile, err := os.Open(p.Command)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"open plugin source\")\n\t}\n\tdefer pluginFile.Close()\n\tpluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read plugin source\")\n\t}\n\tpluginMetadata, err := metadata.Parse(metadata.DebugFunc(p.Debugf), p.CleanFilename(), string(pluginFileB))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"metadata.Parse\")\n\t}\n\tvars := make(map[string]interface{})\n\tfor _, pluginVar := range pluginMetadata.Vars {\n\t\tif pluginVar.Default == \"\" {\n\t\t\t// skip values with no default\n\t\t\tcontinue\n\t\t}\n\t\tvars[pluginVar.Name] = pluginVar.DefaultValue()\n\t}\n\treturn vars, nil\n}\n","sourceCodeStart":112,"sourceCodeEnd":146,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/variables.go#L112-L146","documentation":"This error is wrapped by loadVariablesFromPluginMetadata when io.ReadAll fails while reading the opened plugin file's contents (capped at 1MB via io.LimitReader). It means the plugin file was successfully opened but its bytes could not be read from disk (I/O failure after open). The library wraps the underlying OS error so callers know the failure occurred at the read-plugin-source step of variable extraction.","triggerScenarios":"os.Open succeeded on pkg/plugins file (pkg/plugins/variables.go:130) but io.ReadAll(io.LimitReader(pluginFile, 1_000_000)) returned a non-nil error — e.g. file deleted/truncated between open and read, disk I/O error, read permission revoked mid-read, or a device/FIFO that errors on read.","commonSituations":"Plugin binary replaced or removed while the app loads variables from it; network-mounted plugin directory with flaky connectivity; filesystem errors (bad sectors, EIO); plugin file is a special device that fails on read; SELinux/AppArmor denying read after open.","solutions":["Check the wrapped cause (%+v of the error) for the underlying errno (EIO, ESTALE, EACCES) and fix the filesystem/permission issue","Re-download or reinstall the plugin file — it is likely corrupted, truncated, or missing","Verify the plugin path points to a regular readable file (os.Stat + Mode().IsRegular()) before loading","Move plugin files off network/unstable mounts to local disk","Rerun the load; transient I/O errors may not recur"],"exampleFix":"// before\npluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))\nif err != nil {\n\treturn nil, errors.Wrap(err, \"read plugin source\")\n}\n// after\nif fi, statErr := os.Stat(path); statErr != nil || !fi.Mode().IsRegular() {\n\treturn nil, fmt.Errorf(\"plugin %s is not a regular file\", path)\n}\npluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))\nif err != nil {\n\treturn nil, errors.Wrap(err, \"read plugin source\")\n}","handlingStrategy":"validation","validationCode":"func pluginReadable(path string) error {\n\tfi, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !fi.Mode().IsRegular() {\n\t\treturn fmt.Errorf(\"%s is not a regular file\", path)\n\t}\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tf.Close()\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"vars, err := loadVariablesFromPluginMetadata(p)\nif err != nil {\n\tif strings.Contains(fmt.Sprintf(\"%+v\", err), \"read plugin source\") {\n\t\tlog.Printf(\"plugin file unreadable, skipping: %v\", err)\n\t\treturn defaultVars, nil\n\t}\n\treturn nil, err\n}","preventionTips":["Stat the plugin path and confirm it is a regular, readable file before loading","Store plugins on local, stable storage rather than network mounts","Never mutate or delete plugin files while the application is loading them","Log errors with %+v to surface the wrapped errno for diagnosis"],"tags":["go","filesystem","io","plugins"],"backgroundTag":"file-read-failed","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}