matryer/xbar · error

open vars json file

Error message

open vars json file

What it means

loadVariablesFromJSONFile (pkg/plugins/variables.go:102-107) opens <plugin.Command>.vars.json. A missing file is deliberately ignored (returns nil, nil), but any other os.Open error is wrapped as 'open vars json file'. This means the vars file exists but is inaccessible — e.g. permission denied, path is a directory, or too many open files.

Source

Thrown at pkg/plugins/variables.go:107

	}
	// add the json file vars to the defaults,
	// and return them.
	for k, v := range jsonFileVars {
		defaultVars[k] = v
	}
	return defaultVars, nil
}

// loadVariablesFromJSONFile gets a list of environment variable friendly
// key=value pairs.
func (p *Plugin) loadVariablesFromJSONFile() (map[string]interface{}, error) {
	variablesJSONFilename := p.Command + variableJSONFileExt
	f, err := os.Open(variablesJSONFilename)
	if err != nil && os.IsNotExist(err) {
		// no .vars.json file - no probs
		return nil, nil
	} else if err != nil {
		return nil, errors.Wrap(err, "open vars json file")
	}
	defer f.Close()
	b, err := io.ReadAll(io.LimitReader(f, 1_000_000))
	if err != nil {
		return nil, err
	}
	var vars map[string]interface{}
	if err := json.Unmarshal(b, &vars); err != nil {
		return nil, errors.Wrap(err, "json.Unmarshal")
	}
	return vars, nil
}

func (p *Plugin) loadVariablesFromPluginMetadata() (map[string]interface{}, error) {
	// read the plugin metadata for default values
	pluginFile, err := os.Open(p.Command)
	if err != nil {
		return nil, errors.Wrap(err, "open plugin source")

View on GitHub (pinned to d624239058)

Solutions

  1. Inspect the file: `ls -la <plugin>.vars.json` — check it is a regular file with read permission.
  2. Fix permissions/ownership or remove a directory/placeholder at that path.
  3. Raise the open-file limit (ulimit -n) if many plugins load at once.
  4. Check audit logs / use errors %+v to see the exact errno behind the wrapper.
Defensive patterns

Strategy: try-catch

Validate before calling

varsPath := p.Command + ".vars.json"
if info, err := os.Stat(varsPath); err == nil {
	if !info.Mode().IsRegular() {
		log.Printf("%s is not a regular file", varsPath)
	}
	if info.Mode().Perm()&0400 == 0 {
		log.Printf("%s not readable", varsPath)
	}
}

Try / catch

vars, err := p.loadVariables()
if err != nil {
	var se syscall.Errno
	if errors.As(errors.Cause(err), &se) && errors.Is(se, syscall.EMFILE) {
		log.Printf("too many open files while loading vars: %v", err)
	}
	return nil, err
}

Prevention

When it happens

Trigger: Permission denied on the .vars.json or a parent directory; the path resolves to a directory; a broken symlink; EMFILE (too many open files) when many plugins load concurrently; I/O error on the underlying storage.

Common situations: xbar runs with many plugins simultaneously and hits the open-file limit; backup/sync placeholder directories named *.vars.json; file created by another user (root) with restrictive mode.

Related errors


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