matryer/xbar · error

reading

Error message

reading

What it means

parseOutput reads plugin stdout line by line with a scanner to build the menu item list. This error wraps any read error other than io.EOF encountered while scanning, preserving the underlying cause (e.g. broken pipe, file descriptor issues) under the message 'reading'.

Source

Thrown at pkg/plugins/parse.go:126

			if len(ancestorItems) > 0 {
				parentItem := ancestorItems[len(ancestorItems)-1]
				parentItem.Items = append(parentItem.Items, item)
			} else {
				if item.Params.Alternate {
					// add to previous item, as Alternate
					previousItem.Alternate = item
				} else if item.Params.Dropdown {
					// if Dropdown=false then don't include it
					items.ExpandedItems = append(items.ExpandedItems, item)
				}
			}
		} else {
			items.CycleItems = append(items.CycleItems, item)
		}
		previousItem = item
	}
	if err != nil && err != io.EOF {
		return items, errors.Wrap(err, "reading")
	}
	return items, nil
}

func parseSeparator(src string) (string, bool) {
	text := strings.TrimSpace(src)
	if text == separator {
		return "", true
	}
	for strings.HasPrefix(text, nesting) {
		text = strings.TrimPrefix(text, nesting)
		if text == separator {
			return src[:len(src)-3], true
		}
	}
	return src, false
}

View on GitHub (pinned to d624239058)

Solutions

  1. Inspect errors.Cause(err) / the wrapped message to find the underlying read failure
  2. Make sure the plugin script exits cleanly (check exit code, avoid SIGKILL)
  3. Check the plugin doesn't produce output exceeding scanner limits without proper handling
  4. Verify the plugin executable is stable and doesn't crash mid-output

Example fix

// before
#!/bin/bash
while true; do cat hugefile; done   // killed mid-write
// after
#!/bin/bash
cat hugefile && exit 0               // write fully, exit cleanly
Defensive patterns

Strategy: try-catch

Try / catch

items, err := parseOutput(ctx, name, out)
if err != nil {
    var wrapped interface{ Unwrap() error }
    if errors.As(err, &target) || errors.Unwrap(err) != nil {
        log.Printf("plugin %s: read failure: %v", name, errors.Unwrap(err))
    }
    return fallbackItems // degrade gracefully instead of crashing
}

Prevention

When it happens

Trigger: The bufio scanner's Err() returns a non-EOF error while parseOutput consumes plugin output — e.g. the plugin process was killed mid-write, the pipe was closed abnormally, or the output reader was interrupted via the ctx cancellation path.

Common situations: Plugin script crashes or is OOM-killed while still writing output; system resource limits closing the pipe; test scenarios (TestErrors etc.) feeding intentionally broken readers.

Related errors


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