Skip to content

Fix panic on bare @ CLI argument#3772

Open
Copilot wants to merge 4 commits intomainfrom
copilot/fix-cli-crash-on-at-argument
Open

Fix panic on bare @ CLI argument#3772
Copilot wants to merge 4 commits intomainfrom
copilot/fix-cli-crash-on-at-argument

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

Bug Fix

What was the bug?

tsgo @ panics because parseResponseFile receives an empty string after stripping the @ prefix, and vfs.ReadFile("") asserts the path is absolute.

How did you fix it?

Fixed Common.ReadFile in the VFS layer to gracefully return ("", false) for non-absolute paths instead of panicking. This is the correct level to handle the issue since ReadFile already has a boolean return to signal failure. The fix protects all callers of VFS ReadFile, not just response file parsing.

Testing

  • Added TestParseEmptyResponseFile regression test confirming no panic and that a diagnostic error is produced.
  • Updated the existing ReadFileUnrooted test in iovfs to expect graceful failure instead of a panic.

Copilot AI linked an issue May 8, 2026 that may be closed by this pull request
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CLI crash when using @ as an argument Fix panic on bare @ CLI argument May 8, 2026
Copilot AI requested a review from RyanCavanaugh May 8, 2026 17:18
Comment thread internal/tsoptions/commandlineparser.go Outdated
Comment on lines +166 to +169
if fileName == "" {
p.errors = append(p.errors, ast.NewCompilerDiagnostic(diagnostics.Cannot_read_file_0, fileName))
return
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this in tryReadFile?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the guard into tryReadFile in the latest commit.

@RyanCavanaugh
Copy link
Copy Markdown
Member

@copilot listen to Jake

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
Copilot AI requested a review from RyanCavanaugh May 8, 2026 17:50
Comment on lines 213 to 218
// this function adds a compiler diagnostic if the file cannot be read
if fileName == "" {
errors = append(errors, ast.NewCompilerDiagnostic(diagnostics.Cannot_read_file_0, fileName))
return "", errors
}
text, e := readFile(fileName)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ultimately I'm confused why readFile does not handle this, too? I each refactor makes me see that there's a problem further down the stack

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the fix to Common.ReadFile in the VFS layer — it now returns ("", false) for non-absolute paths instead of panicking. Reverted the tryReadFile guard since it's no longer needed.

@RyanCavanaugh
Copy link
Copy Markdown
Member

@copilot listen to Jake

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
@RyanCavanaugh RyanCavanaugh marked this pull request as ready for review May 8, 2026 18:23
Copilot AI review requested due to automatic review settings May 8, 2026 18:23
Comment on lines +142 to +144
if tspath.GetEncodedRootLength(path) == 0 {
return "", false
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point, surely this means RootAndPath should just return nil. I don't know if I like how deep this is going, though. it was sort of nice to know when you passed a bad path in

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash in the CLI when a bare @ argument is provided by preventing a VFS-level panic and adding a regression test to ensure the parser reports a diagnostic instead.

Changes:

  • Updated vfs.Common.ReadFile to return ("", false) for non-absolute paths rather than panicking.
  • Adjusted iovfs tests to expect graceful failure (no panic) on unrooted ReadFile calls.
  • Added a command-line parser regression test for tsgo @ to ensure an error is produced without panicking.
Show a summary per file
File Description
internal/vfs/iovfs/iofs_test.go Updates the unrooted ReadFile test to assert graceful failure instead of a panic.
internal/vfs/internal/internal.go Changes Common.ReadFile to avoid panicking on non-absolute paths and return ok=false.
internal/tsoptions/commandlineparser_test.go Adds a regression test ensuring bare @ produces diagnostics rather than crashing.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Comment on lines 141 to 145
func (vfs *Common) ReadFile(path string) (contents string, ok bool) {
if tspath.GetEncodedRootLength(path) == 0 {
return "", false
}
fsys, _, rest := vfs.RootAndPath(path)
t.Parallel()
// Regression test: `tsgo @` (bare @ with no filename) should not panic.
cmdLine := tsoptions.ParseCommandLine([]string{"@"}, tsoptionstest.NewVFSParseConfigHost(nil, "/", true))
assert.Assert(t, len(cmdLine.Errors) > 0, "expected an error for empty response file name")
testutil.AssertPanics(t, func() { fs.ReadFile("bar") }, `vfs: path "bar" is not absolute`)
contents, ok := fs.ReadFile("bar")
assert.Assert(t, !ok)
assert.Assert(t, contents == "")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File argument of @ crashes CLI

4 participants