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

  1. Run `ls -la` on the .vars.json path to check whether it is a directory, symlink, or has bad permissions.
  2. Fix ownership/permissions: chown to the xbar user and chmod 600 the file.
  3. Remove and re-create the vars file via the plugin settings UI if it is corrupt or a placeholder.
  4. 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

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


AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02). Data as JSON: /api/errors/78990b0ec91c3119. Report an issue: GitHub.