Skip to content

fix: Avoid panic for unanchorable/non-UTF8 git paths#11106

Merged
anthonyshew merged 13 commits intovercel:mainfrom
biru-codeastromer:bug-fix
Mar 28, 2026
Merged

fix: Avoid panic for unanchorable/non-UTF8 git paths#11106
anthonyshew merged 13 commits intovercel:mainfrom
biru-codeastromer:bug-fix

Conversation

@biru-codeastromer
Copy link
Copy Markdown
Contributor

@biru-codeastromer biru-codeastromer commented Nov 12, 2025

What

Prevent a runtime panic in crates/turborepo-scm/src/git.rs when git emits paths that cannot be anchored to the turbo root (e.g. corrupted filenames, non-parent paths) or when git stdout contains non-UTF8 bytes. Instead of unwrap() → crash, errors propagate through the existing Result chain and the change detector falls back to treating all packages as changed.

Why

GitHub Actions CI was failing for repositories that contain unusual filenames (Cyrillic / corrupted / non-UTF8). The panic originated in add_files_from_stdout's .unwrap() calls and caused --affected CI runs to crash.

How

crates/turborepo-scm/src/git.rs

  • add_files_from_stdout now returns Result<(), Error> — replaced .unwrap() on RelativeUnixPath::new() and reanchor_path_from_git_root_to_turbo_root() with ? propagation
  • All 3 call sites in changed_files updated to propagate with ?

crates/turborepo-scope/src/change_detector.rs

  • Replaced process::exit(1) + eprintln! with a fail-safe fallback: on any SCM error, log via tracing::warn! and return all packages as changed (same pattern as the existing InvalidRange handler)
  • Removed std::process and Error as ScmError imports — the library crate no longer terminates the process or couples to specific SCM error variant internals

crates/turborepo-repository/src/change_mapper/mod.rs

  • Added AllPackageChangeReason::ScmError { error: String } variant for downstream consumers to understand why all packages were selected

crates/turborepo-query/src/lib.rs + affected_tasks.rs

  • Added match arms for the new ScmError variant in the GraphQL query layer

Behavior

When git emits unprocessable paths, instead of panicking:

  1. The error propagates from add_files_from_stdout through changed_files to changed_packages
  2. changed_packages catches it, logs a warning via tracing::warn!, and conservatively treats all packages as changed
  3. CI runs everything rather than crashing — run summaries, telemetry, and TUI teardown all execute normally

Fix #10403

@biru-codeastromer biru-codeastromer requested a review from a team as a code owner November 12, 2025 06:02
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Nov 12, 2025

@biru-codeastromer is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@biru-codeastromer biru-codeastromer changed the title fix(scm/git): avoid panic for unanchorable/non-UTF8 git paths , gracefully handle path errors fix(scm/git): Avoid panic for unanchorable/non-UTF8 git paths , gracefully handle path errors Nov 12, 2025
Copy link
Copy Markdown
Contributor

@anthonyshew anthonyshew left a comment

Choose a reason for hiding this comment

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

Hi, thanks for the PR!

Let's do a hard failure (exit 1) here instead of a warning. My worry is that users will not see the warning, and suddenly start running all of their CI because of one misbehaving file. If that file were to make it to the default branch of the repo, that would result in some dramatic slowdowns in a large enough repo.

Before this PR, the CI run would crash, and the user's code would never be able to make it through CI. So, erroring with a useful message instead of a crash report would be a meaningful DX improvement, while preserving existing behavior.

@biru-codeastromer
Copy link
Copy Markdown
Contributor Author

Thanks good call. I updated the change detector so SCM path errors now produce a hard failure (exit 1) with a focused, actionable error message on stderr instead of logging a warning and defaulting to “all packages changed”. This makes the failure visible in CI logs and avoids accidentally running full CI due to a stray problematic filename.

Copy link
Copy Markdown
Contributor

@anthonyshew anthonyshew left a comment

Choose a reason for hiding this comment

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

Please read and correct Claude's output before submitting it in a pull request. If you are not able to verify the completeness of the provided implementation because you do not understand it, please do not send a pull request.

The Vercel review is correct. You need to update the PR description.

Additionally, lets add some unit testing in accordance with this fix. Sorry for not mentioning this earlier.

biru-codeastromer and others added 3 commits November 13, 2025 01:26
Co-authored-by: Anthony Shew <anthonyshew@gmail.com>
Removed outdated documentation for the add_files_from_stdout function.
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
@biru-codeastromer
Copy link
Copy Markdown
Contributor Author

I will be adding the unit test soon

biru-codeastromer and others added 3 commits November 13, 2025 09:24
# Conflicts:
#	crates/turborepo-scm/src/git.rs
#	crates/turborepo-scope/src/change_detector.rs
Fix the actual panic source in add_files_from_stdout by replacing
.unwrap() with error propagation. When SCM errors occur (unanchorable
paths, non-UTF8 filenames), conservatively treat all packages as
changed instead of crashing.

- add_files_from_stdout now returns Result<(), Error> instead of
  panicking on malformed git paths
- change_detector catches SCM errors and falls back to all-packages-
  changed (matching the existing InvalidRange pattern)
- Uses tracing::warn instead of eprintln for structured logging
- Removes process::exit from library crate, restoring proper error
  flow through the Result chain
@anthonyshew anthonyshew changed the title fix(scm/git): Avoid panic for unanchorable/non-UTF8 git paths , gracefully handle path errors fix: Avoid panic for unanchorable/non-UTF8 git paths Mar 28, 2026
Verify that malformed git paths produce errors instead of panics:
- Absolute paths rejected by RelativeUnixPath::new
- Unanchorable paths rejected by reanchor_path_from_git_root
- Error propagates through SCM::changed_files to callers
Copy link
Copy Markdown
Contributor

@anthonyshew anthonyshew left a comment

Choose a reason for hiding this comment

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

Hi, thanks for getting this started. I ended up needing to tweak the approach due to some changes we made to our internal logging infrastructure. Let's ship it!

@anthonyshew anthonyshew enabled auto-merge (squash) March 28, 2026 05:33
The catch-all Err(err) arm was too broad — it swallowed legitimate
errors like bad git refs, breaking test_query_affected_exit_code_error_returns_2.
Only Error::Path (unanchorable/non-UTF8 paths) should fall back to
all-packages-changed. Other SCM errors propagate normally.
@anthonyshew anthonyshew merged commit 5f45fdb into vercel:main Mar 28, 2026
45 of 55 checks passed
github-actions bot added a commit that referenced this pull request Mar 28, 2026
## Release v2.8.22-canary.1

Versioned docs: https://v2-8-22-canary-1.turborepo.dev

### Changes

- release(turborepo): 2.8.21-canary.20 (#12470) (`c5a4690`)
- fix: Show run summary after TUI exits (#12471) (`ffa47d1`)
- release(turborepo): 2.8.21 (#12472) (`be8dc50`)
- fix: Avoid panic for unanchorable/non-UTF8 git paths (#11106)
(`5f45fdb`)

Co-authored-by: Turbobot <turbobot@vercel.com>
github-actions bot added a commit that referenced this pull request Mar 30, 2026
## Release v2.9.0

Versioned docs: https://v2-9-0.turborepo.dev

### Changes

- release(turborepo): 2.8.21 (#12472) (`be8dc50`)
- fix: Avoid panic for unanchorable/non-UTF8 git paths (#11106)
(`5f45fdb`)
- release(turborepo): 2.8.22-canary.1 (#12473) (`f929b6d`)
- fix: Handle Yarn 2+ in @turbo/codemod install commands (#12477)
(`64e5ffd`)
- release(turborepo): 2.8.22-canary.2 (#12479) (`be8cf64`)
- feat: Accept `experimentalCI` key in turbo.json task config (#12480)
(`bff5591`)
- release(turborepo): 2.8.22-canary.3 (#12481) (`cd2d25b`)
- fix: Prevent pnpm overrides from corrupting resolved peer-dep variants
(#12482) (`91d31cf`)
- release(turborepo): 2.8.22-canary.4 (#12483) (`a6eabc6`)
- fix: Skip writing unchanged files during slow-path cache restore
(#12484) (`b7c0001`)
- release(turborepo): 2.8.22-canary.5 (#12486) (`3155a35`)
- fix: Replace pre-existing symlinks with directories during cache
restore (#12488) (`d07bee8`)
- release(turborepo): 2.8.22-canary.6 (#12490) (`5e9ba83`)
- fix: Follow symlinks during workspace package discovery (#12489)
(`f39b370`)
- release(turborepo): 2.8.22-canary.7 (#12491) (`c03cc5f`)
- fix: Reduce inotify watch count via gitignore-aware directory walking
on Linux (#12398) (`664fd88`)
- release(turborepo): 2.8.22-canary.8 (#12492) (`841fe79`)

---------

Co-authored-by: Turbobot <turbobot@vercel.com>
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.

crates/turborepo-scm/src/git.rs panics in GitHub Actions

2 participants