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
- Inspect the plugin file's header/metadata comments and fix syntax to match the expected metadata format
- Verify the file is non-empty and a valid plugin script (correct shebang, complete metadata block)
- Reinstall/re-download the plugin — the file may be truncated or corrupted
- Check the plugin was written for a compatible version of this library (metadata format changes across versions)
- 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
- Lint plugin scripts' metadata blocks in CI before distribution
- Never hand-edit plugin metadata comments without validating against the parser
- Pin plugin files to versions compatible with the library's metadata format
- Verify downloads (checksum/size) so truncated files are rejected before parsing
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
- malformed xbar.var format
- malformed xbar.var format (missing select options)
- malformed xbar.var format (empty select options)
- malformed xbar.var format (default not in select options)
- unknown xbar.var type: %s
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/a48cc96ae0556183.
Report an issue: GitHub.