How to Debug a Failed Percy Snapshot Locally
Trace a failed Percy snapshot from test invocation to asset discovery, rendering, upload, and build finalization, using local logs and Percy’s hosted debug tools.
Start by rerunning the same test command locally through Percy. Use --debug when investigating asset discovery without creating a Percy build or uploading snapshots. Use --verbose when you need detailed CLI logs and want the run to create a build and upload snapshots so you can inspect hosted evidence. Percy’s --debug flag is not an interactive debugger.
A useful diagnosis separates five stages: test invocation, asset discovery, browser rendering and readiness, snapshot upload, and build finalization. First identify which stage failed from the local output and Percy’s build classification; then change only the setting or integration implicated by that evidence.
1. Reproduce the failing command locally
Run the project’s usual test command with Percy’s CLI wrapper. Substitute your actual test command and arguments:
npx percy exec --debug -- npm test -- --runInBand
The portion after -- is the command Percy should run. For example, a project might use npx percy exec --debug -- npm run test:e2e. Preserve the same test selection, environment variables, base URL, and relevant fixture data as the failing CI job; otherwise you may reproduce a different path.
In this mode Percy runs SDK functions such as DOM capture and asset discovery, while suppressing build creation and snapshot upload. It is useful for questions such as whether the expected page resources are discovered. It cannot show how Percy’s hosted build renderer handled an uploaded snapshot, because there is no uploaded snapshot in this run.
For the CLI options supported by your installed version, consult the Percy CLI reference and check local help with npx percy exec --help. CLI options can change; if a flag is rejected, confirm the installed CLI version and its help output before changing the command.
2. Pick the mode that answers your question
| Mode | Use it when | What to expect |
|---|---|---|
--debug |
You are investigating asset discovery and want to avoid a build or snapshot uploads. | Extra asset-discovery information; no Percy build is created and snapshots are not uploaded. |
--verbose |
You need comprehensive CLI logs and hosted build evidence. | The run can create a build and upload snapshots; inspect the resulting build in Percy. |
--dry-run |
You need to check which snapshot names the CLI would produce. | Prints snapshot names without taking snapshots. It does not diagnose rendered output. |
Use the least disruptive mode that can answer the question. Asset discovery is local evidence; upload, build processing, and hosted rendering require a run that produces a Percy build. See the CLI reference for the flags and usage supported by your CLI version.
3. Classify the failure before tuning settings
Percy’s failure guide distinguishes build-level failures, such as no snapshots, missing finalization, resource upload problems, and rendering timeouts, from snapshot-level failures, such as an SDK call that never happened, page-load failure, or upload failure. Match the observed message to the narrowest classification in the Snapshots Missing or Failed guide before increasing timeouts or changing capture configuration.
| Symptom | First checks | Evidence-based next step |
|---|---|---|
| No snapshots uploaded | Did the test execute? Did it call the Percy SDK snapshot function? Is the test connected to the Percy integration path? Is PERCY_TOKEN available? |
Run the correct wrapped command and inspect the build failure classification. |
| Expected snapshot call did not happen | Check test selection, conditional branches, and integration wiring. | Make sure the selected test reaches the SDK or percy snapshot call. |
| CSS, fonts, images, or other resources are missing | Inspect requested URLs, response status, duration, host access, authentication, and lazy loading. | Use asset-discovery output and hosted Network logs; adjust allowed hosts or readiness only when the evidence points there. |
| Page-load or network-idle timeout | Identify pending requests and whether capture starts before the page or target is ready. | Wait for a meaningful selector or bounded delay; tune the relevant timeout to the observed request pattern. |
| Snapshot upload failure | Check the snapshot URL and whether the runner has stable network egress. | Retry once as a transient-failure diagnostic; investigate persistent connectivity or access failures. |
| Parallel build remains incomplete | Confirm all shards ran and identify which pipeline stage finalizes the build. | Run percy build:finalize after all parallel shards finish. |
4. Verify test invocation, token, and parallel setup
When Percy reports no snapshots, begin with the test process rather than image settings. Confirm the command actually ran, the intended test was selected, and the test reached a Percy snapshot call. Confirm PERCY_TOKEN is present in the process environment for an uploading run. Do not paste the token into shared logs, issue comments, or a command transcript.
Parallel runs need their parallel-build configuration to agree with the pipeline. Depending on the setup, Percy documents PERCY_PARALLEL_NONCE and PERCY_PARALLEL_TOTAL; the build must also be finalized after all shards complete. A missing finalization step can leave a build waiting even when individual shards captured snapshots. Check the Percy failure guide for the applicable parallel workflow.
5. Inspect asset discovery and page readiness
For missing assets, record the specific URL and request result rather than guessing at a global timeout. Ask:
- Does the runner reach the asset host, and does that host require authentication or a custom header?
- Does the asset request fail, return an unexpected status, or remain pending?
- Is the image or content lazy-loaded only after scrolling or another interaction?
- Does the page or target element exist before Percy captures the DOM?
Percy’s CLI snapshot configuration documents waitForSelector and waitForTimeout for readiness cases. Use a selector that represents the content you need, or a bounded delay when readiness cannot be expressed by a selector. These are not fixes for a blocked host or a request that never completes. See the Percy CLI configuration documentation for syntax and supported configuration.
The CLI reference also documents --allowed-hostname for asset discovery and --network-idle-timeout for asset-discovery timing. Treat these as targeted controls: only change allowed hosts when discovery evidence shows a host needs to be included, and adjust network-idle timing after identifying which requests keep the page active. --disable-cache can help determine whether cache behavior is involved. Confirm these options against the installed CLI reference.
6. Use Percy’s hosted build to inspect rendering and network evidence
When the local run does not explain a hosted rendering or upload issue, open the Percy project’s Builds tab, select the failed build, and choose Debug on the failed-build banner or snapshot card. Smart Debug provides an Overview, Network logs, and Troubleshoot views. The Overview summarizes the detected classification and relevant log line; Network logs show request URLs, statuses, and timing; Troubleshoot connects the detected failure with guided steps.
For a hang, timeout, or failure without a clear ERROR or WARN entry, inspect the full build logs. Percy’s current Smart Debug documentation says logs are retained for one month and that downloading build logs requires Percy CLI 1.28.4 or later. These are service details that can change, so verify them in the live Smart Debug documentation when relying on them.
7. Diagnose upload and timeout failures separately
A snapshot can be captured locally and still fail during upload. Check that the snapshot URL is valid and that the runner can make the required network connections. Unstable connectivity can cause a transient failure, but repeated retries do not resolve persistent egress restrictions, authentication issues, or invalid URLs.
For page-load and network-idle failures, inspect which requests remain pending and whether the application has long-lived connections. If the intended UI is ready while unrelated traffic continues, wait for a meaningful selector or use an appropriate documented timeout setting. Avoid increasing a timeout blindly: it can make a run slower without addressing a missing resource, dead request, or incorrect test flow.
8. A compact local-to-hosted workflow
- Copy the failing CI test command and preserve its test selection and relevant environment.
- Run it with
npx percy exec --debug --when the question is asset discovery. - Classify the failure: invocation, asset discovery, readiness/rendering, upload, or parallel finalization.
- Use local output to check snapshot calls, discovered resources, and timing.
- When hosted evidence is required, rerun with
--verboseand inspect that Percy build’s Overview, Network logs, and full logs. - Make one targeted change, rerun the relevant command, and compare the evidence.
Or skip the browser setup
If you need a clean capture of a page while diagnosing its visible content, ScreenshotNeo can return a screenshot with one API request. Its API is separate from Percy and does not debug Percy builds or visual-test integrations. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo removes known cookie and consent banners, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, no card required.
Performance, reliability, and cost considerations
- Keep local diagnostics focused. A non-uploading debug run is useful for asset discovery; use an uploading run only when you need build-side evidence.
- Prefer targeted waits. Waiting for a real page element is usually more informative than extending a broad timeout when only one component controls readiness.
- Separate transient from persistent failures. A single retry can reveal intermittent connectivity; repeated failures call for checking network access, host authorization, and URLs.
- Protect secrets. Keep Percy tokens in the CI secret store or local environment and redact them from logs shared outside the team.
- Control parallel completion. Ensure all expected shards report completion before build finalization, or incomplete builds can obscure the actual snapshot result.
FAQ
Does Percy --debug open a debugger?
No. It adds asset-discovery diagnostics and suppresses build creation and snapshot upload. It is not an interactive browser debugger.
Can I use --debug to see Percy’s hosted rendering?
No. For hosted rendering and request evidence, create an uploading run, then inspect its Percy build and Smart Debug views.
When should I use --verbose?
Use it when you need detailed CLI logs and want the run to create a build and upload snapshots for hosted investigation.
Why is the build still waiting after all tests pass?
In a parallel setup, check that the expected shards completed and that the pipeline ran percy build:finalize afterward.
Should I increase the timeout first?
No. First identify pending requests or the page element that is not ready. Increase a relevant timeout only when the logs support that diagnosis.


