charmbracelet/vhs · error · parser.Error

Wait+ expects Line or Screen

Error message

Wait+ expects Line or Screen

What it means

vhs's Wait command blocks until a pattern appears on the screen; Wait+ optionally takes a match target. parseWait accepts 'Wait+ Line' (match on a single line) or 'Wait+ Screen' (match the whole screen); any other token after the '+' raises this error. It exists because Wait+ is strict: the only valid plus-arguments are the literal strings 'Line' and 'Screen'.

Source

Thrown at parser/parser.go:200

	case token.COPY:
		return []Command{p.parseCopy()}
	case token.PASTE:
		return []Command{p.parsePaste()}
	case token.ENV:
		return []Command{p.parseEnv()}
	default:
		p.errors = append(p.errors, NewError(p.cur, "Invalid command: "+p.cur.Literal))
		return []Command{{Type: token.ILLEGAL}}
	}
}

func (p *Parser) parseWait() Command {
	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 {

View on GitHub (pinned to c073383b5d)

Solutions

  1. Use exactly 'Wait+ Line' or 'Wait+ Screen' (capitalized, no quotes needed unless you prefer quoting the string).
  2. If you want to wait for specific text, use Wait with a regex after the type: 'Wait+ Screen<regex>...' as supported by vhs (e.g. 'Wait+ Screen /pattern/').
  3. Drop the '+' and use plain 'Wait' which defaults to Line matching.

Example fix

// before (.tape)
Wait+ line
// after (.tape)
Wait+ Line
Defensive patterns

Strategy: validation

Validate before calling

func validWaitPlus(arg string) bool { return arg == "Line" || arg == "Screen" }

Type guard

func isWaitTarget(s string) bool { switch s { case "Line", "Screen": return true }; return false }

Prevention

When it happens

Trigger: Writing 'Wait+ Line' / 'Wait+ Screen' with anything other than exactly the token STRING 'Line' or 'Screen' after '+', e.g. 'Wait+ line' (lowercase), 'Wait+ Text', 'Wait+ 5', or 'Wait+ Pattern'.

Common situations: Case-sensitivity mistakes ('line' vs 'Line'); guessing the Wait+ option name from memory; copying syntax from other wait libraries that accept arbitrary targets.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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