{"record":{"id":"8f6c7cbb39756ed8","repo":"gastownhall/beads","slug":"open-batch-file-w","errorCode":null,"errorMessage":"open batch file: %w","messagePattern":"open batch file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/batch.go","lineNumber":111,"sourceCode":"\t\t\tif c := metrics.Global(); c != nil {\n\t\t\t\tc.CloseEventAndAdd(evt)\n\t\t\t}\n\t\t}()\n\n\t\tproxied := usesProxiedServer()\n\t\tif !proxied && store == nil {\n\t\t\treturn fmt.Errorf(\"no database connection available (%s)\", diagHint())\n\t\t}\n\n\t\tfilePath, _ := cmd.Flags().GetString(\"file\")\n\t\tdryRun, _ := cmd.Flags().GetBool(\"dry-run\")\n\t\tcommitMsg, _ := cmd.Flags().GetString(\"message\")\n\n\t\tvar reader io.Reader\n\t\tif filePath != \"\" {\n\t\t\tf, err := os.Open(filePath) // #nosec G304 -- user-supplied batch file\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"open batch file: %w\", err)\n\t\t\t}\n\t\t\tdefer f.Close()\n\t\t\treader = f\n\t\t} else {\n\t\t\treader = cmd.InOrStdin()\n\t\t}\n\n\t\tops, err := parseBatchScript(reader)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing batch input: %w\", err)\n\t\t}\n\n\t\tif dryRun {\n\t\t\t// In dry-run mode, just echo what would run. This is helpful for\n\t\t\t// shell script authors verifying their scripts before running.\n\t\t\tfor _, op := range ops {\n\t\t\t\tfmt.Fprintf(cmd.OutOrStdout(), \"line %d: %s\\n\", op.line, op.raw)\n\t\t\t}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/batch.go#L93-L129","documentation":"When 'bd batch --file <path>' is given, the file is opened with os.Open before parsing. Any OS-level open failure (nonexistent path, permission denied, is-a-directory) is wrapped as 'open batch file: %w'. The error surfaces the underlying *os.PathError so the real cause is visible.","triggerScenarios":"--file points to a file that does not exist, lacks read permission, is a directory, or the path is malformed — os.Open returns a non-nil err.","commonSituations":"Typo in the --file path; relative path resolved from unexpected cwd in scripts/CI; file generated by a prior step that failed; running as a user without read permission; passing a directory instead of a file.","solutions":["Check the wrapped PathError: fix the path or permissions it reports","Verify the file exists and is readable: ls -l <file>","Use an absolute path for --file in scripts and CI","If input should come from stdin, omit --file (it defaults to cmd.InOrStdin)"],"exampleFix":"// before\nbd batch --file ./ops.txxt\n// after\nbd batch --file ./ops.txt   # or omit --file to read stdin","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(filePath); err != nil || info.IsDir() {\n\treturn fmt.Errorf(\"batch file %q is missing or not a regular file\", filePath)\n}","typeGuard":"func readableFile(p string) bool { info, err := os.Stat(p); return err == nil && info.Mode().IsRegular() }","tryCatchPattern":"f, err := os.Open(filePath)\nif err != nil {\n\tvar perr *os.PathError\n\tif errors.As(err, &perr) { /* surface perr.Err: not-exist vs permission */ }\n\treturn fmt.Errorf(\"open batch file: %w\", err)\n}","preventionTips":["Use absolute paths for --file in scripts and CI pipelines","Verify the file was produced successfully before batching (check prior step exit codes)","Ensure the executing user has read permission on the batch file","Omit --file when input should come from stdin"],"tags":["file-io","batch","go"],"backgroundTag":"file-open-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}