charmbracelet/vhs · error · parser.Error
Source tape: ${srcPath} is empty
Error message
Source tape: ${srcPath} is empty What it means
After reading the file, parseSource checks len(srcTape) == 0 and reports "Source tape: <path> is empty" if the included tape has no content. An empty include contributes nothing and is treated as a mistake.
Source
Thrown at parser/parser.go:712
p.errors = append(p.errors, NewError(p.peek, notFoundErr))
p.nextToken()
return []Command{cmd}
}
// Check if source tape contains nested Source command
d, err := os.ReadFile(srcPath) //nolint:gosec
if err != nil {
readErr := fmt.Sprintf("Unable to read file: %s", srcPath)
p.errors = append(p.errors, NewError(p.peek, readErr))
p.nextToken()
return []Command{cmd}
}
srcTape := string(d)
// Check source tape is NOT empty
if len(srcTape) == 0 {
readErr := fmt.Sprintf("Source tape: %s is empty", srcPath)
p.errors = append(p.errors, NewError(p.peek, readErr))
p.nextToken()
return []Command{cmd}
}
srcLexer := lexer.New(srcTape)
srcParser := New(srcLexer)
// Check not nested source
srcCmds := srcParser.Parse()
for _, cmd := range srcCmds {
if cmd.Type == token.SOURCE {
p.errors = append(p.errors, NewError(p.peek, "Nested Source detected"))
p.nextToken()
return []Command{cmd}
}
}
// Check src errorsView on GitHub (pinned to c073383b5d)
Solutions
- Add valid tape instructions to the sourced file
- Remove the Source line if the include is not needed
- Verify file size with `wc -c` / `ls -l` before running
Example fix
// before (empty file) // after echo 'Type "hello"' > empty.tape
Defensive patterns
Strategy: validation
Validate before calling
p := "nested.tape"
info, err := os.Stat(p)
if err == nil && info.Size() == 0 {
return fmt.Errorf("Source target %s is empty", p)
} Type guard
func tapeNonEmpty(path string) bool {
info, err := os.Stat(path)
return err == nil && info.Size() > 0
} Try / catch
if err := parse(tape); err != nil && strings.Contains(err.Error(), "is empty") {
return fmt.Errorf("populate or remove empty include: %w", err)
} Prevention
- Delete placeholder tapes instead of leaving them empty
- Verify file sizes after LFS/checkout steps in CI
- Fail fast on zero-byte artifacts in the build pipeline
When it happens
Trigger: Parse() on a tape sourcing a zero-byte .tape file (e.g. `touch empty.tape` then `Source "empty.tape"`), or a file truncated by a failed checkout/save.
Common situations: Placeholder files created but never filled in; interrupted writes; git LFS files not materialized (0 bytes).
Related errors
- Expected file with .tape extension
- 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/f5ed3b98adf74b84.
Report an issue: GitHub.