matryer/xbar · error
Open
Error message
Open
What it means
LoadVariableValues (pkg/plugins/variables.go:36-42) opens <pluginDir>/<installedPluginPath>.vars.json and wraps any os.Open failure other than 'not exists' with the message 'Open'. A missing file is intentionally treated as an empty map, so this error means the file exists but cannot be opened (permissions, path is a directory, I/O error). It surfaces as 'Open: <os error>'.
Source
Thrown at pkg/plugins/variables.go:42
}
filename := filepath.Join(pluginDir, installedPluginPath+variableJSONFileExt)
err = ioutil.WriteFile(filename, b, 0666)
if err != nil {
return errors.Wrap(err, "WriteFile")
}
return nil
}
// LoadVariableValues loads the variables for a plugin.
func LoadVariableValues(pluginDir, installedPluginPath string) (map[string]interface{}, error) {
filename := filepath.Join(pluginDir, installedPluginPath+variableJSONFileExt)
f, err := os.Open(filename)
if err != nil {
if os.IsNotExist(err) {
// no file - but not an error, just empty map
return map[string]interface{}{}, nil
}
return nil, errors.Wrap(err, "Open")
}
defer f.Close()
b, err := io.ReadAll(io.LimitReader(f, 1_000_000 /* ~1MB */))
if err != nil {
return nil, errors.Wrap(err, "ReadAll")
}
var values map[string]interface{}
err = json.Unmarshal(b, &values)
if err != nil {
return nil, errors.Wrap(err, "json.Unmarshal")
}
return values, nil
}
func (p *Plugin) loadVariablesAsEnvVars() ([]string, error) {
vars, err := p.loadVariables()
if err != nil {
return nil, errors.Wrap(err, "loadVariables")View on GitHub (pinned to d624239058)
Solutions
- Run `ls -la` on the .vars.json path to check whether it is a directory, symlink, or has bad permissions.
- Fix ownership/permissions: chown to the xbar user and chmod 600 the file.
- Remove and re-create the vars file via the plugin settings UI if it is corrupt or a placeholder.
- Check ACLs/mandatory access control (getfacl, audit logs) if permissions look correct but access still fails.
Defensive patterns
Strategy: try-catch
Validate before calling
info, err := os.Stat(filepath.Join(pluginDir, installedPluginPath+".vars.json"))
switch {
case os.IsNotExist(err):
// fine — LoadVariableValues returns an empty map
case err != nil:
// stat error, likely same cause as Open failure
log.Printf("vars path problem: %v", err)
case info.IsDir():
log.Printf("%s is a directory, not a vars file", info.Name())
case info.Mode().Perm()&0400 == 0:
log.Printf("vars file is not readable")
} Try / catch
values, err := plugins.LoadVariableValues(pluginDir, installedPluginPath)
if err != nil {
if strings.Contains(err.Error(), "Open") && errors.Is(errors.Cause(err), fs.ErrPermission) {
values = map[string]interface{}{} // degrade to defaults
} else {
return err
}
} Prevention
- Run xbar as a single consistent user so files are not root-owned.
- Exclude the plugins directory from sync tools that create placeholder dirs.
- Check readability of *.vars.json after restoring from backups.
- Keep ACLs on the plugin dir simple (no restrictive ACLs).
When it happens
Trigger: The .vars.json path exists but is a directory; read permission denied on the file or a parent directory; the path contains invalid characters; SELinux/AppArmor denies access; the file lives on a failed/unmounted mount.
Common situations: Backup/sync tools (Dropbox, iCloud) replace the vars file with a placeholder directory; the user ran xbar once as root and the file is now root-owned with 0600; a broken symlink points to an inaccessible target.
Related errors
- open vars json file
- create directory %s for plugin
- create plugin file %s
- set executable permission on plugin entry point
- ReadDir
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/78990b0ec91c3119.
Report an issue: GitHub.