matryer/xbar · error

metadata.Parse

Error message

metadata.Parse

What it means

This error is wrapped when metadata.Parse fails to parse the plugin's metadata (embedded #!/bin/... shebang script with metadata comments) from the plugin file's contents. It means the file was read fine, but its metadata section (name, version, vars) is malformed or unsupported. The library wraps it so callers know variable loading failed at the parse stage.

Source

Thrown at pkg/plugins/variables.go:134

		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")
	}
	defer pluginFile.Close()
	pluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))
	if err != nil {
		return nil, errors.Wrap(err, "read plugin source")
	}
	pluginMetadata, err := metadata.Parse(metadata.DebugFunc(p.Debugf), p.CleanFilename(), string(pluginFileB))
	if err != nil {
		return nil, errors.Wrap(err, "metadata.Parse")
	}
	vars := make(map[string]interface{})
	for _, pluginVar := range pluginMetadata.Vars {
		if pluginVar.Default == "" {
			// skip values with no default
			continue
		}
		vars[pluginVar.Name] = pluginVar.DefaultValue()
	}
	return vars, nil
}

View on GitHub (pinned to d624239058)

Solutions

  1. Inspect the plugin file's header/metadata comments and fix syntax to match the expected metadata format
  2. Verify the file is non-empty and a valid plugin script (correct shebang, complete metadata block)
  3. Reinstall/re-download the plugin — the file may be truncated or corrupted
  4. Check the plugin was written for a compatible version of this library (metadata format changes across versions)
  5. Enable p.Debugf / metadata.DebugFunc to see the parser's specific complaint

Example fix

// before (malformed header)
#!/bin/bash
# name: myplugin
vars: FOO=${FOO:-}
// after (valid metadata block)
#!/bin/bash
# name: myplugin
# version: 1.0.0
# foo: description of foo
# FOO: ${FOO:-default}
Defensive patterns

Strategy: validation

Validate before calling

func hasValidPluginHeader(path string) error {
	b, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	if len(b) == 0 {
		return fmt.Errorf("plugin %s is empty", path)
	}
	if !bytes.HasPrefix(b, []byte("#!")) {
		return fmt.Errorf("plugin %s missing shebang", path)
	}
	return nil
}

Try / catch

vars, err := loadVariablesFromPluginMetadata(p)
if err != nil {
	if strings.Contains(fmt.Sprintf("%+v", err), "metadata.Parse") {
		log.Printf("invalid plugin metadata in %s: %v", p.CleanFilename(), err)
		return map[string]interface{}{}, nil
	}
	return nil, err
}

Prevention

When it happens

Trigger: loadVariablesFromPluginMetadata calls metadata.Parse(debugFunc, p.CleanFilename(), string(pluginFileB)) (pkg/plugins/variables.go:134) and the parser rejects the content — e.g. missing/invalid shebang, malformed metadata comment block, unparseable variable declarations, empty or non-plugin file.

Common situations: Hand-edited plugin script broke the metadata comment syntax; plugin from an older/newer version uses metadata format the parser rejects; file is empty (0 bytes) or a binary without expected metadata; wrong file extension/filename confusing CleanFilename; truncated download (cut at 1MB LimitReader) slicing the metadata block.

Related errors


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