tsenart/vegeta · error

bad body: %w

Error message

bad body: %w

What it means

Returned when a target line's body directive (a line starting with '@') points to a file that cannot be read. The parser calls os.ReadFile on the path following '@' and wraps the error as "bad body".

Source

Thrown at lib/targets.go:314

			return fmt.Errorf("bad method: %s", tokens[0])
		}
		tgt.Method = tokens[0]
		if _, err = url.ParseRequestURI(tokens[1]); err != nil {
			return fmt.Errorf("bad URL: %s, %w", tokens[1], err)
		}
		tgt.URL = tokens[1]
		line = strings.TrimSpace(sc.Peek())
		if line == "" || startsWithHTTPMethod(line) {
			return nil
		}
		for sc.Scan() {
			if line = strings.TrimSpace(sc.Text()); line == "" {
				break
			} else if strings.HasPrefix(line, "#") {
				continue
			} else if strings.HasPrefix(line, "@") {
				if tgt.Body, err = os.ReadFile(line[1:]); err != nil {
					return fmt.Errorf("bad body: %w", err)
				}
				break
			}
			tokens = strings.SplitN(line, ":", 2)
			if len(tokens) < 2 {
				return fmt.Errorf("bad header: %s", line)
			}
			for i := range tokens {
				if tokens[i] = strings.TrimSpace(tokens[i]); tokens[i] == "" {
					return fmt.Errorf("bad header: %s", line)
				}
			}
			// Add key/value directly to the http.Header (map[string][]string).
			// http.Header.Add() canonicalizes keys but vegeta is used
			// to test systems that require case-sensitive headers.
			tgt.Header[tokens[0]] = append(tgt.Header[tokens[0]], tokens[1])
		}
		if err = sc.Err(); err != nil {

View on GitHub (pinned to cf58112690)

Solutions

  1. Verify the file after '@' exists and is readable at that path (use an absolute path).
  2. Run vegeta from the directory you expect, or make the @ path absolute.
  3. Check file permissions for the vegeta process user.
  4. Confirm the line really begins with '@' only when pointing at a body file; escape or fix accidental '@' usages.

Example fix

// before
POST http://api/
@data/payload.json
// after (from repo root)
POST http://api/
@/abs/path/data/payload.json
Defensive patterns

Strategy: validation

Validate before calling

func validateBodyRef(line string) error {
    if !strings.HasPrefix(line, "@") { return nil }
    path := strings.TrimSpace(line[1:])
    if path == "" { return fmt.Errorf("empty body path") }
    f, err := os.Open(path)
    if err != nil { return err }
    return f.Close()
}

Try / catch

if err := vegeta.NewTargets(r); err != nil { 
    if strings.Contains(err.Error(), "bad body:") {
        return fmt.Errorf("@-referenced body file unreadable: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: A targets file contains "@/path/to/body.json" where the file does not exist, lacks read permission, or the path is relative to the wrong working directory.

Common situations: Referencing a request body file with a relative path while running vegeta from another directory, forgetting to create the payload file, permission-restricted files in CI containers.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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