Skip to content

Implement aggressive stack trace normalization for better error grouping #6120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

amcaplan
Copy link
Contributor

Summary

This PR implements aggressive stack trace normalization to ensure identical errors always produce identical stack traces, regardless of environment differences. This will significantly improve error grouping in our telemetry system.

Problem

Previously, the same error would create different stack traces depending on:

  • Installation location (global vs local)
  • Package manager (npm/yarn/pnpm)
  • Operating system (Windows/Mac/Linux)
  • User home directory
  • CI/CD environment

This caused identical errors to be split into multiple groups in Bugsnag, making it difficult to identify and prioritize issues.

Solution

  1. Aggressive path normalization: Strip ALL absolute path prefixes

    • For node_modules paths: Extract only the part after node_modules/
    • For other paths: Remove all leading slashes to make them relative
  2. Preserve original stack traces: Store the original stack trace in Bugsnag metadata under original_stacktrace for debugging

Examples

All of these paths now normalize to the same result:

/Users/john/project/node_modules/@shopify/cli/dist/index.js
C:/Users/jane/AppData/Roaming/npm/node_modules/@shopify/cli/dist/index.js
/home/bob/.local/share/pnpm/global/5/node_modules/@shopify/cli/dist/index.js
→ @shopify/cli/dist/index.js

Testing

  • ✅ All existing tests updated and passing
  • ✅ Added security tests for path traversal
  • ✅ Added test for metadata preservation
  • ✅ Type checking passes
  • ✅ Linting passes

Notes

  • Investigated using StackTracey's built-in fileShort property, but it adds relative path prefixes that make the problem worse
  • The aggressive normalization ensures identical errors = identical stack traces, period
  • Original stack traces are preserved for debugging, so no information is lost

🤖 Generated with Claude Code

amcaplan and others added 2 commits July 16, 2025 14:19
This change significantly improves how errors are grouped in our telemetry
system by normalizing environment-specific paths in stack traces.

Key improvements:
- Fix critical security vulnerabilities:
  * Sanitize path traversal sequences (../ and ./)
  * Add input validation with 1000 char length limit
  * Preserve Windows drive letters as <DRIVE_C>, <DRIVE_D> etc
- Fix correctness bugs:
  * UUID pattern now matches anywhere in path (not just between slashes)
  * Version pattern now matches at end of paths without trailing slash
- Add comprehensive path normalizations:
  * Home directories → <HOME>
  * Temp directories → <TEMP>
  * Global package managers → <GLOBAL_NPM>, <GLOBAL_YARN>, <GLOBAL_PNPM>
  * Webpack chunks → chunk-<HASH>.js
  * CI/CD environments → <CI_WORKSPACE>
  * Container paths → <CONTAINER>
  * Version numbers → @<VERSION>
  * UUIDs → <UUID>
- Add 56 comprehensive tests including security edge cases
- Add early exit optimization for performance

This prevents identical errors from being split into multiple groups due to
differences in user environments, making error monitoring more effective.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
…ping

This change implements much more aggressive stack trace normalization to ensure
identical errors always produce identical stack traces, regardless of environment.

Key changes:
- Strip ALL absolute path prefixes (no more <HOME>, <CI_WORKSPACE>, etc)
- For node_modules: extract ONLY the part after node_modules/
- For other paths: remove all leading slashes to make them relative
- Preserve original stack trace in Bugsnag metadata for debugging

Examples of normalization:
- /Users/john/project/node_modules/@shopify/cli/dist/index.js → @shopify/cli/dist/index.js
- /home/user/.yarn/cache/@shopify-cli-npm-3.45.0/node_modules/@shopify/cli/dist/index.js → @shopify/cli/dist/index.js
- /github/workspace/packages/cli-kit/src/error.js → packages/cli-kit/src/error.js

This ensures identical errors produce identical stack traces regardless of:
- Installation location (global vs local)
- Package manager (npm/yarn/pnpm)
- Operating system (Windows/Mac/Linux)
- User home directory
- CI/CD environment

The original stack trace is preserved in Bugsnag metadata under
"original_stacktrace" for debugging purposes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@amcaplan amcaplan requested a review from a team as a code owner July 16, 2025 16:22
Copy link
Contributor

We detected some changes at packages/*/src and there are no updates in the .changeset.
If the changes are user-facing, run pnpm changeset add to track your changes and include them in the next release CHANGELOG.

Caution

DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release.

Copy link
Contributor

github-actions bot commented Jul 16, 2025

Coverage report

St.
Category Percentage Covered / Total
🟡 Statements
78.24% (+0.19% 🔼)
13043/16670
🟡 Branches
72.44% (+0.19% 🔼)
6357/8776
🟡 Functions
78.19% (+0.02% 🔼)
3374/4315
🟡 Lines
78.65% (+0.19% 🔼)
12351/15703
Show files with reduced coverage 🔻
St.
File Statements Branches Functions Lines
🟢
... / checkout_ui_extension.ts
80% (-20% 🔻)
0% (-50% 🔻)
50% (-50% 🔻)
80% (-20% 🔻)
🟢
... / bundle.ts
100%
50% (-33.33% 🔻)
100% 100%
🟢
... / common.ts
83.33% (-7.58% 🔻)
78.57% (-13.1% 🔻)
75% (+3.57% 🔼)
80.95% (-8.52% 🔻)

Test suite run success

3073 tests passing in 1315 suites.

Report generated by 🧪jest coverage report action from fdfd987

Comment on lines 55 to 56
['macOS home', '/Users/john/project/file.js', 'Users/john/project/file.js'],
['Linux home', '/home/jane/work/app.js', 'home/jane/work/app.js'],
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't user names be removed here?

Comment on lines 61 to 67
[
'Windows AppData Roaming',
'/Users/LENOVO/AppData/Roaming/npm/node_modules/@shopify/cli/dist/chunk-AE3MLJMV.js',
'@shopify/cli/dist/chunk-<HASH>.js',
],
['Windows AppData Local', '/Users/john/AppData/Local/Programs/app.js', 'Users/john/AppData/Local/Programs/app.js'],
['Windows AppData Temp', '/Users/john/AppData/Local/Temp/test.js', 'Users/john/AppData/Local/Temp/test.js'],
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here for Windows AppData Local and Temp

@amcaplan amcaplan marked this pull request as draft July 17, 2025 10:25
@amcaplan
Copy link
Contributor Author

Sorry @isaacroldan, this is still WIP. I've converted to draft.

- Strip ALL environment-specific path prefixes to improve error grouping
- Remove user home directories, temp paths, CI workspaces entirely
- Handle yarn/pnpm cache paths by extracting only the package-relative path
- Aggressively strip Windows AppData paths (Local/Programs, Roaming, etc.)
- Preserve original stack traces in Bugsnag metadata for debugging
- Fix linter errors by moving inline comments to separate lines

This ensures identical errors produce identical stack traces regardless of:
- Installation method (npm, yarn, pnpm, global vs local)
- User home directory location
- Operating system (Windows/Mac/Linux)
- CI/CD environment (GitHub Actions, GitLab, etc.)
- Container or temporary directory paths

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
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.

2 participants