Link errors to commits with Suspect Commits
The Suspect Commits feature in Frontend Observability surfaces the Git commit most likely responsible for an error on the error summary page, so you can jump from a stack trace to a candidate fix without leaving Grafana. Enabling commit hash injection adds a directly recorded signal: when an error first appears, the SDK reports the build’s SHA, and Suspect Commits pins that commit at the top of the candidate list.
To enable this, inject the current commit hash into your built JavaScript at build time. The Faro Web SDK reads it and includes it as meta.app.gitHash on every telemetry payload. You can inject the hash with the Faro bundler plugins, the Faro CLI, or directly in the Faro Web SDK configuration.
Note
The Faro Web SDK transmits the injected commit hash to Grafana Cloud as part of Faro telemetry and stores it with the error’s first-seen record. If you operate in a regulated industry or your repository is proprietary, review your organization’s data-handling policies before enabling this feature.
Minimum versions:
@grafana/faro-web-sdk(and@grafana/faro-react): 2.7.0- Bundler plugins:
@grafana/faro-webpack-plugin0.12.0,@grafana/faro-rollup-plugin0.11.0,@grafana/faro-esbuild-plugin0.6.0,@grafana/faro-metro-plugin0.2.0 - CLI (for post-build injection):
@grafana/faro-cli0.10.0
Inject the commit hash with the bundler plugins
If you use the Faro bundler plugins to upload source maps, the same plugins can inject the commit hash. The plugin resolves the hash in this priority order:
- Explicit
gitHashvalue passed to the plugin - Auto-detected via
git rev-parse HEADat build time
If neither resolves, the plugin emits [Faro] Git hash could not be resolved to the build log and no hash is injected. The build still succeeds.
Auto-detection via git rev-parse HEAD
When gitHash is not specified, the plugin runs git rev-parse HEAD during the build. This works for most local development environments and CI setups where the .git directory is present in the build context:
new FaroSourceMapUploaderPlugin({
appName: '$your-app-name',
endpoint: '$your-faro-sourcemap-api-url',
// ...other required options
// gitHash auto-detected from git rev-parse HEAD
});Warning
Multi-stage Docker builds commonly exclude
.gitvia.dockerignore, which causes auto-detection to silently fail. The build succeeds but no hash is injected. Either keep.gitin the build context or setgitHashexplicitly (see below).
Explicit override
Set gitHash explicitly when auto-detection won’t pick the right SHA:
- Multi-stage Docker builds, or any build context without access to
.git - GitHub Actions
pull_requestevents, wheregit rev-parse HEADandprocess.env.GITHUB_SHAboth resolve to a synthetic merge commit that doesn’t exist on any branch. To point at the PR head, pass${{ github.event.pull_request.head.sha }}through as anenvvar. - Any environment where the desired SHA differs from the local checkout
new FaroSourceMapUploaderPlugin({
appName: '$your-app-name',
endpoint: '$your-faro-sourcemap-api-url',
// ...other required options
gitHash: process.env.FARO_GIT_HASH,
});On GitHub Actions, expose the PR head SHA to the build step.
Use pull_request.head.sha so the injected SHA points at the PR head, not the synthetic merge commit GitHub creates for pull_request events:
- name: build
env:
FARO_GIT_HASH: ${{ github.event.pull_request.head.sha || github.sha }}
run: yarn buildPost-build injection via the Faro CLI
If you can’t run the bundler plugin at build time (for example, you ship pre-built artifacts produced elsewhere), the @grafana/faro-cli package exposes an inject-git-hash command that mirrors inject-bundle-id and patches the hash into existing JavaScript artifacts after the fact:
npx @grafana/faro-cli inject-git-hash \
--app-name '$your-app-name' \
--git-hash $(git rev-parse HEAD) \
--files 'dist/**/*.js'Refer to the faro-JavaScript-bundler-plugins repository for the full CLI reference.
Set gitHash directly in the Faro Web SDK configuration
If you don’t use the Faro bundler plugins, you can set app.gitHash directly when initializing the Faro Web SDK. Because browsers have no process.env, the commit SHA must be embedded into the bundle at build time:
1. Make the SHA available to the build:
For local builds:
export GIT_HASH=$(git rev-parse HEAD)For CI environments, use the appropriate environment variable:
- GitHub Actions:
export GIT_HASH=$GITHUB_SHA - Jenkins:
export GIT_HASH=$GIT_COMMIT - GitLab CI:
export GIT_HASH=$CI_COMMIT_SHA
2. Configure your bundler to inline it.
For Create React App and Next.js, no extra config is needed. They automatically inline prefixed env vars. Set REACT_APP_GIT_HASH (CRA) or NEXT_PUBLIC_GIT_HASH (Next.js) instead of GIT_HASH in step 1, and reference it directly as process.env.REACT_APP_GIT_HASH / process.env.NEXT_PUBLIC_GIT_HASH.
For Vite, no extra configuration is needed. Vite embeds import.meta.env.VITE_*. Set VITE_GIT_HASH in step 1 and reference it as import.meta.env.VITE_GIT_HASH.
For Webpack, use DefinePlugin:
// webpack.config.js
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.DefinePlugin({
'process.env.GIT_HASH': JSON.stringify(process.env.GIT_HASH),
}),
],
};For Rollup, use @rollup/plugin-replace:
// rollup.config.js
import replace from '@rollup/plugin-replace';
export default {
// ...
plugins: [
replace({
preventAssignment: true,
'process.env.GIT_HASH': JSON.stringify(process.env.GIT_HASH),
}),
],
};For esbuild, use the define option:
// build.js
import * as esbuild from 'esbuild';
await esbuild.build({
// ...
define: {
'process.env.GIT_HASH': JSON.stringify(process.env.GIT_HASH),
},
});3. Reference it in your Faro initialization:
import { initializeFaro } from '@grafana/faro-web-sdk';
initializeFaro({
url: '$your-faro-collector-url',
app: {
name: '$your-app-name',
version: '1.0.0',
gitHash: process.env.GIT_HASH, // or import.meta.env.VITE_GIT_HASH for Vite
},
// ...other config
});Only the meta.app.gitHash check below applies when using this approach. The bundler plugins set window.__faroGitHash_<app-name> only.
Verify the commit hash is captured
After a successful build, you can confirm the hash flows end-to-end:
- Build log: Grep for
[Faro] Git hash could not be resolved. If the plugin couldn’t determine a SHA, this string appears in the build output. Its absence means the plugin resolved a hash successfully. - Bundle: Open DevTools console on a page using the bundle and run
window.__faroGitHash_<your-app-name>. Expect a 40-character SHA. (Bundler plugin path only.) - Telemetry: In the browser Network tab, inspect a Faro
/collectrequest.meta.app.gitHashshould be set on the payload.
If the hash is missing, the most common cause is a build context without .git (multi-stage Docker, .dockerignore excluding .git). Refer to the Explicit override section to set gitHash explicitly.


