{"record":{"id":"d6e43b7e7b478d09","repo":"matryer/xbar","slug":"reading","errorCode":null,"errorMessage":"reading","messagePattern":"reading","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/parse.go","lineNumber":126,"sourceCode":"\t\t\tif len(ancestorItems) > 0 {\n\t\t\t\tparentItem := ancestorItems[len(ancestorItems)-1]\n\t\t\t\tparentItem.Items = append(parentItem.Items, item)\n\t\t\t} else {\n\t\t\t\tif item.Params.Alternate {\n\t\t\t\t\t// add to previous item, as Alternate\n\t\t\t\t\tpreviousItem.Alternate = item\n\t\t\t\t} else if item.Params.Dropdown {\n\t\t\t\t\t// if Dropdown=false then don't include it\n\t\t\t\t\titems.ExpandedItems = append(items.ExpandedItems, item)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\titems.CycleItems = append(items.CycleItems, item)\n\t\t}\n\t\tpreviousItem = item\n\t}\n\tif err != nil && err != io.EOF {\n\t\treturn items, errors.Wrap(err, \"reading\")\n\t}\n\treturn items, nil\n}\n\nfunc parseSeparator(src string) (string, bool) {\n\ttext := strings.TrimSpace(src)\n\tif text == separator {\n\t\treturn \"\", true\n\t}\n\tfor strings.HasPrefix(text, nesting) {\n\t\ttext = strings.TrimPrefix(text, nesting)\n\t\tif text == separator {\n\t\t\treturn src[:len(src)-3], true\n\t\t}\n\t}\n\treturn src, false\n}\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/parse.go#L108-L144","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect errors.Cause(err) / the wrapped message to find the underlying read failure","Make sure the plugin script exits cleanly (check exit code, avoid SIGKILL)","Check the plugin doesn't produce output exceeding scanner limits without proper handling","Verify the plugin executable is stable and doesn't crash mid-output"],"exampleFix":"// before\n#!/bin/bash\nwhile true; do cat hugefile; done   // killed mid-write\n// after\n#!/bin/bash\ncat hugefile && exit 0               // write fully, exit cleanly","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"items, err := parseOutput(ctx, name, out)\nif err != nil {\n    var wrapped interface{ Unwrap() error }\n    if errors.As(err, &target) || errors.Unwrap(err) != nil {\n        log.Printf(\"plugin %s: read failure: %v\", name, errors.Unwrap(err))\n    }\n    return fallbackItems // degrade gracefully instead of crashing\n}","preventionTips":["Ensure the plugin script exits cleanly after writing output","Avoid killing plugin processes mid-write","Keep output within scanner buffer limits"],"tags":["plugins","stdout","io","parsing"],"backgroundTag":"stdout-read-failed","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}