tsenart/vegeta · error

error reading

Error message

error reading %s: %s

What it means

After successfully opening the body file, attack() reads it fully with io.ReadAll; if reading fails (I/O error rather than open error) the filename and underlying error are wrapped. This indicates the file exists but its contents could not be read.

Solutions

  1. Check the wrapped underlying error for the real cause (I/O error, permission, etc.).
  2. Copy the body to a regular local file and pass that path instead of a device/mounted path.
  3. Re-run with a smaller/known-good body file to isolate the failing input.
Defensive patterns

Strategy: try-catch

Validate before calling

if b, err := os.ReadFile(bodyPath); err != nil {
    return fmt.Errorf("body file unreadable: %w", err)
}

Try / catch

if _, err := os.ReadFile(bodyPath); err != nil {
    log.Fatalf("pre-check read of body %s failed: %v", bodyPath, err)
}

Prevention

When it happens

Trigger: `-body` file that becomes unreadable mid-read, a special/character device or FIFO that errors during read, or hardware/permission errors surfacing during ReadAll.

Common situations: Body file on a flaky network mount; passing a device path like /dev/stdin in an environment where stdin cannot be read; disk I/O errors.

Related errors


AI-assisted analysis of tsenart/vegeta@cf58112690 (2026-08-31). Data as JSON: /api/errors/355216985706f18a. Report an issue: GitHub.

Appendix: source

Thrown at attack.go:148

	net.DefaultResolver.PreferGo = true

	files := map[string]io.Reader{}
	for _, filename := range []string{opts.targetsf, opts.bodyf} {
		if filename == "" {
			continue
		}
		f, err := file(filename, false)
		if err != nil {
			return fmt.Errorf("error opening %s: %s", filename, err)
		}
		defer f.Close()
		files[filename] = f
	}

	var body []byte
	if bodyf, ok := files[opts.bodyf]; ok {
		if body, err = io.ReadAll(bodyf); err != nil {
			return fmt.Errorf("error reading %s: %s", opts.bodyf, err)
		}
	}

	var (
		tr       vegeta.Targeter
		src      = files[opts.targetsf]
		hdr      = opts.headers.Header
		proxyHdr = opts.proxyHeaders.Header
	)

	switch opts.format {
	case vegeta.JSONTargetFormat:
		tr = vegeta.NewJSONTargeter(src, body, hdr)
	case vegeta.HTTPTargetFormat:
		tr = vegeta.NewHTTPTargeter(src, body, hdr)
	default:
		return fmt.Errorf("format %q isn't one of [%s]",
			opts.format, strings.Join(vegeta.TargetFormats, ", "))

View on GitHub (pinned to cf58112690)