{"record":{"id":"f5ed3b98adf74b84","repo":"charmbracelet/vhs","slug":"source-tape-srcpath-is-empty","errorCode":null,"errorMessage":"Source tape: ${srcPath} is empty","messagePattern":"Source tape: (.+?) is empty","errorType":"validation","errorClass":"parser.Error","httpStatus":null,"severity":"error","filePath":"parser/parser.go","lineNumber":712,"sourceCode":"\t\tp.errors = append(p.errors, NewError(p.peek, notFoundErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\t// Check if source tape contains nested Source command\n\td, err := os.ReadFile(srcPath) //nolint:gosec\n\tif err != nil {\n\t\treadErr := fmt.Sprintf(\"Unable to read file: %s\", srcPath)\n\t\tp.errors = append(p.errors, NewError(p.peek, readErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tsrcTape := string(d)\n\t// Check source tape is NOT empty\n\tif len(srcTape) == 0 {\n\t\treadErr := fmt.Sprintf(\"Source tape: %s is empty\", srcPath)\n\t\tp.errors = append(p.errors, NewError(p.peek, readErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tsrcLexer := lexer.New(srcTape)\n\tsrcParser := New(srcLexer)\n\n\t// Check not nested source\n\tsrcCmds := srcParser.Parse()\n\tfor _, cmd := range srcCmds {\n\t\tif cmd.Type == token.SOURCE {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Nested Source detected\"))\n\t\t\tp.nextToken()\n\t\t\treturn []Command{cmd}\n\t\t}\n\t}\n\n\t// Check src errors","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/charmbracelet/vhs/blob/c073383b5de0b1f57bf514113029c306bc986539/parser/parser.go#L694-L730","documentation":"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.","triggerScenarios":"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.","commonSituations":"Placeholder files created but never filled in; interrupted writes; git LFS files not materialized (0 bytes).","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"],"exampleFix":"// before\n(empty file)\n// after\necho 'Type \"hello\"' > empty.tape","handlingStrategy":"validation","validationCode":"p := \"nested.tape\"\ninfo, err := os.Stat(p)\nif err == nil && info.Size() == 0 {\n    return fmt.Errorf(\"Source target %s is empty\", p)\n}","typeGuard":"func tapeNonEmpty(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.Size() > 0\n}","tryCatchPattern":"if err := parse(tape); err != nil && strings.Contains(err.Error(), \"is empty\") {\n    return fmt.Errorf(\"populate or remove empty include: %w\", err)\n}","preventionTips":["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"],"tags":["parser","validation","empty-file"],"backgroundTag":"empty-input-file","analyzedSha":"c073383b5de0b1f57bf514113029c306bc986539","analyzedAt":"2026-09-02T01:53:05.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}