Allure report is a blank page

You generated allure-report/, double-clicked index.html, and got a white page — or the Allure logo and a spinner that never stops.

Nothing is corrupt. The report just cannot load its own data.

What Allure actually ships

index.html is a single-page application shell. The results are not in it. They are in sibling files that the shell fetches at runtime:

allure-report/
├── index.html          ← the shell, ~2 KB of bootstrap
├── app.js              ← the application
├── data/
│   ├── suites.json     ← fetched over XHR
│   ├── behaviors.json
│   └── test-cases/*.json   ← one per test, fetched on click
├── widgets/*.json      ← the dashboard tiles
└── plugin/

Open that from file:// and every one of those fetches is blocked. A local file has an opaque origin, and the same-origin policy refuses XHR against it — deliberately, because the alternative is any downloaded HTML file being able to read your home directory.

Console says: Access to XMLHttpRequest at 'file:///…/data/suites.json' from origin 'null' has been blocked by CORS policy — or, in Firefox, Cross-Origin Request Blocked.

That message is the whole diagnosis. The report is fine; the protocol is wrong.

Fixing it for yourself

Serve it over HTTP. Allure ships the server:

allure open allure-report        # serves the generated directory
allure serve allure-results      # generate + serve in one step

Any static server does the same job — python -m http.server inside allure-report/, or npx serve. The point is http:// instead of file://.

Fixing it for everyone else

The above requires every reader to have the Allure CLI, the results directory, and a terminal. In practice that means one person looks at the report and the rest read a screenshot of it.

Three ways out, in increasing order of usefulness:

1. Single-file mode. Allure 2 can inline everything:

allure generate allure-results --clean --single-file

One index.html that opens anywhere. The file gets large on suites of any size, some plugins degrade, and you have given up the per-test JSON drill-down that makes Allure worth using. Fine as an email attachment, poor as the canonical report.

2. Static hosting. A bucket, Pages, an internal nginx. Real HTTP, report intact. The cost is that you now maintain hosting, and the comments about the failing test happen somewhere else entirely.

3. Publish the directory. Upload allure-report/ as a unit: index.html becomes the report body, and data/, widgets/, app.js and the plugins upload alongside it with their relative references rewritten to the uploaded copies. The XHR calls resolve over HTTPS, the drill-down works, and the report is a URL.

Scripts run inside a sandboxed iframe (allow-scripts, no allow-same-origin), so the SPA behaves exactly as it does locally — see interactive HTML reports.

From CI, that is one step at the end of the job:

- name: Publish Allure report
  if: always()
  run: |
    allure generate allure-results --clean -o allure-report
    # upload the folder; see /docs/ci for the multi-file call

Limits: entry HTML 5 MB; assets 25 MB per file, 250 MB and 500 files per report. A large Allure run has one JSON per test case, so watch the file count on suites in the thousands — --single-file is the escape hatch there.

Why the link is the part that matters

The report exists so someone reads the failure. Once it is a URL, reviewers open the failing test and comment on that test, in the report, instead of pasting the stack trace into chat (comment on HTML). Publish the same report id on every run and each build appends a revision, so a flake's history is one page.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish an Allure report →

Related