charmbracelet/vhs · error · parser.Error
Invalid regexp pattern: ${literal}
Error message
Invalid regexp pattern: ${literal} What it means
Fires in parseSet when the value given for the WaitPattern setting fails regexp.Compile, i.e. it is not a syntactically valid Go regular expression. The invalid pattern is still stored in cmd.Args and the error is recorded.
Source
Thrown at parser/parser.go:461
// Set <setting> <value>
func (p *Parser) parseSet() Command {
cmd := Command{Type: token.SET}
if token.IsSetting(p.peek.Type) {
cmd.Options = p.peek.Literal
} else {
p.errors = append(p.errors, NewError(p.peek, "Unknown setting: "+p.peek.Literal))
}
p.nextToken()
switch p.cur.Type {
case token.WAIT_TIMEOUT:
cmd.Args = p.parseTime()
case token.WAIT_PATTERN:
cmd.Args = p.peek.Literal
_, err := regexp.Compile(p.peek.Literal)
if err != nil {
p.errors = append(p.errors, NewError(p.peek, "Invalid regexp pattern: "+p.peek.Literal))
}
p.nextToken()
case token.LOOP_OFFSET:
cmd.Args = p.peek.Literal
p.nextToken()
// Allow LoopOffset without '%'
// Set LoopOffset 20
cmd.Args += "%"
if p.peek.Type == token.PERCENT {
p.nextToken()
}
case token.TYPING_SPEED:
cmd.Args = p.peek.Literal
p.nextToken()
// Allow TypingSpeed to have bare units (e.g. 10ms)
// Set TypingSpeed 10ms
if p.peek.Type == token.MILLISECONDS ||
p.peek.Type == token.SECONDS {View on GitHub (pinned to c073383b5d)
Solutions
- Fix the regex syntax, e.g. close unmatched '(' or '[' groups
- Escape special characters that should match literally, e.g. \. for a dot
- Test the pattern with a Go regex tester (RE2 syntax) before putting it in the tape
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at parser/parser.go:461 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of charmbracelet/vhs@c073383b5d (2026-09-02).
Data as JSON: /api/errors/2616b8fb43564ae4.
Report an issue: GitHub.