charmbracelet/vhs · error · parser.Error
Expected control character with args, got ${literal}
Error message
Expected control character with args, got ${literal} What it means
A Ctrl command requires at least one argument (the key to press). If parseCtrl finishes consuming tokens and args is empty, it records 'Expected control character with args, got <literal>' naming the token that started the command. Note the parser still returns a CTRL command with empty Args, so this often accompanies downstream handling of an empty control sequence.
Source
Thrown at parser/parser.go:347
peek.Type == token.BACKSLASH,
peek.Type == token.LEFT,
peek.Type == token.RIGHT,
peek.Type == token.UP,
peek.Type == token.DOWN,
peek.Type == token.STRING && len(peek.Literal) == 1:
args = append(args, peek.Literal)
default:
// Key arguments with len > 1 are not valid
p.errors = append(p.errors,
NewError(p.cur, "Not a valid modifier"),
NewError(p.cur, "Invalid control argument: "+p.cur.Literal))
}
p.nextToken()
}
if len(args) == 0 {
p.errors = append(p.errors, NewError(p.cur, "Expected control character with args, got "+p.cur.Literal))
}
ctrlArgs := strings.Join(args, " ")
return Command{Type: token.CTRL, Args: ctrlArgs}
}
// parseAlt parses an alt command.
// An alt command takes a character to type while the modifier is held down.
//
// Alt+<character>
func (p *Parser) parseAlt() Command {
if p.peek.Type == token.PLUS {
p.nextToken()
if p.peek.Type == token.STRING ||
p.peek.Type == token.ENTER ||
p.peek.Type == token.LEFT_BRACKET ||
p.peek.Type == token.RIGHT_BRACKET ||
p.peek.Type == token.TAB {View on GitHub (pinned to c073383b5d)
Solutions
- Add a key argument after Ctrl, e.g. 'Ctrl+c' or 'Ctrl+Enter'.
- Remove the Ctrl line entirely if no keypress was intended.
Example fix
// before (.tape) Ctrl+ // after (.tape) Ctrl+c
Defensive patterns
Strategy: validation
Validate before calling
func ctrlHasKey(args []string) bool { return len(args) > 0 } Prevention
- Never leave a bare 'Ctrl' or 'Ctrl+' line in a tape
- After editing key combos, re-read the line to confirm a key remains
- Grep tapes for trailing '+' or lone Ctrl/Alt tokens in review
When it happens
Trigger: 'Ctrl' appears with no following key token, e.g. a lone 'Ctrl' line, or 'Ctrl+' where '+' is followed by nothing valid so no argument is ever appended.
Common situations: Incomplete editing of a tape line (deleting the key but leaving Ctrl); truncation of the tape file; copying 'Ctrl+' from a key-combo template without filling in the key.
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 time after ${literal}
- Modifiers must come before other characters
- Not a valid modifier
- Invalid control argument: ${literal}
- Expected alt character, got ${literal}
AI-assisted analysis of charmbracelet/vhs@c073383b5d (2026-09-02).
Data as JSON: /api/errors/2cec54849ecd8ea6.
Report an issue: GitHub.