charmbracelet/vhs · error · parser.Error
Expected path after Screenshot
Error message
Expected path after Screenshot
What it means
parseScreenshot requires a STRING path token after the Screenshot directive. If the next token is not a string, it records "Expected path after Screenshot" and returns. Screenshot writes a capture at that point in the recording, so a destination path is required.
Source
Thrown at parser/parser.go:760
srcCmd.Type == token.OUTPUT {
continue
}
filtered = append(filtered, srcCmd)
}
p.nextToken()
return filtered
}
// parseScreenshot parses screenshot command.
// Screenshot command takes a file path for storing screenshot.
//
// Screenshot <path>
func (p *Parser) parseScreenshot() Command {
cmd := Command{Type: token.SCREENSHOT}
if p.peek.Type != token.STRING {
p.errors = append(p.errors, NewError(p.cur, "Expected path after Screenshot"))
p.nextToken()
return cmd
}
path := p.peek.Literal
// Check if path has .png extension
ext := filepath.Ext(path)
if ext != ".png" {
p.errors = append(p.errors, NewError(p.peek, "Expected file with .png extension"))
p.nextToken()
return cmd
}
cmd.Args = path
p.nextToken()
return cmdView on GitHub (pinned to c073383b5d)
Solutions
- Add a quoted destination: `Screenshot "out.png"`
- Remove the Screenshot line if not needed
- Ensure the path is double-quoted so the lexer emits a STRING token
Example fix
// before Screenshot ./out.png // after Screenshot "./out.png"
Defensive patterns
Strategy: validation
Validate before calling
line := `Screenshot "out.png"`
if strings.HasPrefix(strings.TrimSpace(line), "Screenshot") {
rest := strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(line), "Screenshot"))
if !strings.HasPrefix(rest, `"`) {
return fmt.Errorf("Screenshot requires a quoted path: %s", line)
}
} Type guard
func screenshotHasPath(t token.Token) bool { return t.Type == token.STRING && t.Literal != "" } Try / catch
if err := parse(tape); err != nil && strings.Contains(err.Error(), "Expected path after Screenshot") {
return fmt.Errorf("bad Screenshot directive in %s: %w", tape, err)
} Prevention
- Always quote Screenshot destinations
- Add mid-recording screenshots as complete lines with a path argument
- Run a syntax check on tapes before recording
When it happens
Trigger: A .tape file with bare `Screenshot`, `Screenshot ./out.png` (unquoted), or `Screenshot 42` — parseScreenshot sees peek.Type != token.STRING.
Common situations: Forgetting the argument when adding mid-recording screenshots; using shell-style unquoted paths; editor auto-complete dropping the quotes.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Expected path after Source
- Expected file with .png extension
- Invalid command: ${literal}
- Wait+ expects Line or Screen
- Wait expects positive duration
AI-assisted analysis of charmbracelet/vhs@c073383b5d (2026-09-02).
Data as JSON: /api/errors/99fad3b96917f195.
Report an issue: GitHub.