gastownhall/beads · error

open batch file: %w

Error message

open batch file: %w

What it means

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.

Source

Thrown at cmd/bd/batch.go:111

			if c := metrics.Global(); c != nil {
				c.CloseEventAndAdd(evt)
			}
		}()

		proxied := usesProxiedServer()
		if !proxied && store == nil {
			return fmt.Errorf("no database connection available (%s)", diagHint())
		}

		filePath, _ := cmd.Flags().GetString("file")
		dryRun, _ := cmd.Flags().GetBool("dry-run")
		commitMsg, _ := cmd.Flags().GetString("message")

		var reader io.Reader
		if filePath != "" {
			f, err := os.Open(filePath) // #nosec G304 -- user-supplied batch file
			if err != nil {
				return fmt.Errorf("open batch file: %w", err)
			}
			defer f.Close()
			reader = f
		} else {
			reader = cmd.InOrStdin()
		}

		ops, err := parseBatchScript(reader)
		if err != nil {
			return fmt.Errorf("parsing batch input: %w", err)
		}

		if dryRun {
			// In dry-run mode, just echo what would run. This is helpful for
			// shell script authors verifying their scripts before running.
			for _, op := range ops {
				fmt.Fprintf(cmd.OutOrStdout(), "line %d: %s\n", op.line, op.raw)
			}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped PathError: fix the path or permissions it reports
  2. Verify the file exists and is readable: ls -l <file>
  3. Use an absolute path for --file in scripts and CI
  4. If input should come from stdin, omit --file (it defaults to cmd.InOrStdin)

Example fix

// before
bd batch --file ./ops.txxt
// after
bd batch --file ./ops.txt   # or omit --file to read stdin
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(filePath); err != nil || info.IsDir() {
	return fmt.Errorf("batch file %q is missing or not a regular file", filePath)
}

Type guard

func readableFile(p string) bool { info, err := os.Stat(p); return err == nil && info.Mode().IsRegular() }

Try / catch

f, err := os.Open(filePath)
if err != nil {
	var perr *os.PathError
	if errors.As(err, &perr) { /* surface perr.Err: not-exist vs permission */ }
	return fmt.Errorf("open batch file: %w", err)
}

Prevention

When it happens

Trigger: --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.

Common situations: 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.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/8f6c7cbb39756ed8. Report an issue: GitHub.