charmbracelet/vhs · error · parser.Error

Wait expects positive duration

Error message

Wait expects positive duration

What it means

When a Wait command is followed by '@<duration>' (parsed via parseSpeed into Options), vhs validates the duration with time.ParseDuration and requires it to be strictly positive. This error fires when the Wait timeout is zero or negative, e.g. 'Wait@0s' or 'Wait@-1s'.

Source

Thrown at parser/parser.go:213

	cmd := Command{Type: token.WAIT}

	if p.peek.Type == token.PLUS {
		p.nextToken()
		if p.peek.Type != token.STRING || (p.peek.Literal != "Line" && p.peek.Literal != "Screen") {
			p.errors = append(p.errors, NewError(p.peek, "Wait+ expects Line or Screen"))
			return cmd
		}
		cmd.Args = p.peek.Literal
		p.nextToken()
	} else {
		cmd.Args = "Line"
	}

	cmd.Options = p.parseSpeed()
	if cmd.Options != "" {
		dur, _ := time.ParseDuration(cmd.Options)
		if dur <= 0 {
			p.errors = append(p.errors, NewError(p.peek, "Wait expects positive duration"))
			return cmd
		}
	}

	if p.peek.Type != token.REGEX {
		// fallback to default
		return cmd
	}
	p.nextToken()
	if _, err := regexp.Compile(p.cur.Literal); err != nil {
		p.errors = append(p.errors, NewError(p.cur, fmt.Sprintf("Invalid regular expression '%s': %v", p.cur.Literal, err)))
		return cmd
	}

	cmd.Args += " " + p.cur.Literal

	return cmd
}

View on GitHub (pinned to c073383b5d)

Solutions

  1. Use a positive duration, e.g. 'Wait@5s' or 'Wait@500ms'.
  2. Remove the '@duration' clause entirely to use the default timeout.
  3. Check unit suffixes are valid Go durations (ms, s, m, h).

Example fix

// before (.tape)
Wait@0s Screen
// after (.tape)
Wait@5s Screen
Defensive patterns

Strategy: validation

Validate before calling

func isPositiveDuration(d string) bool { dur, err := time.ParseDuration(strings.TrimPrefix(d, "@")); return err == nil && dur > 0 }

Prevention

When it happens

Trigger: Any 'Wait@<duration>' where time.ParseDuration returns a value <= 0: 'Wait@0', 'Wait@0s', 'Wait@-500ms', or an unparseable value that yields dur <= 0 (parse error is swallowed by the '_').

Common situations: Setting a zero timeout to mean 'no timeout' (vhs does not accept 0 here); accidentally using a negative duration; typos in unit suffix causing the duration to parse to 0.

Related errors


AI-assisted analysis of charmbracelet/vhs@c073383b5d (2026-09-02). Data as JSON: /api/errors/f82a80f438db58b8. Report an issue: GitHub.