Repository navigation
Vitest UI launcher shows Vitest 5's "requires authentication" page instead of the UI #585
Description
Describe the bug
With Vitest 5, clicking Start Vitest UI in the Vite+ group starts the server, the dock swaps to the iframe, and the iframe shows only this text instead of the Vitest UI:
Vitest UI requires authentication. Open the URL with the token printed in the terminal, e.g. http://localhost:51204/__vitest__/?token=...
Since Vitest 5 (vitest-dev/vitest#10583), /__vitest__/ answers 403 unless the request carries ?token=<api token> (which sets a vitest-ui-token cookie and redirects 302 to the clean URL) or already has that cookie. The token is printed by Vitest as UI started at http://localhost:<port>/__vitest__/?token=… and is stored in %LOCALAPPDATA%/vitest/.vitest-secret-token (or node_modules/.vitest/).
The launcher never obtains that token:
- The iframe URL is built as
http://localhost:${port}/__vitest__/with no token (plugin.ts#L117) and returned fromonReadyas-is (#L133-L137). waitForServer()treats any status below 500 as ready (#L192-L205), so the403counts as "ready" and the auth page is embedded. Accepting 403 is fine for "is the port up", but the embedded URL then can never succeed.
Possible fix: take the authenticated URL from the UI started at … line of the session's stdout (via session.getChildProcess()), use it as the iframe URL, and have the readiness probe request that URL and accept only 2xx/3xx. A fallback could read the token file, but that path is a Vitest internal.
Unverified, possibly related (not tested in a browser): the cookie is SameSite=Strict and the launcher hard-codes the localhost host. If DevTools is opened on http://127.0.0.1:<vite port>, the localhost iframe is cross-site, so the browser may not store or send the cookie even when the token is present. Building the iframe URL on the same hostname as the DevTools page would avoid that.
Related: stopping this launcher on Windows leaves the vitest process running, see devframes/devframe#402.
Reproduction
Inline steps below — needs a local Vitest 5 UI (no hosted repro possible).
- Any Vite 8 project with
vitest@5,@vitest/ui@5,@vitejs/devtools@0.7.5and@vitejs/devtools-vitest@0.7.5,devtools: truein the Vite config. Upstream's ownpnpm -C packages/core run playshould show the same, since the workspace usesvitest ^5.0.1. - Run
vite, open DevTools, Vite+ group → Vitest → Start Vitest UI. - The iframe shows the "Vitest UI requires authentication" page.
The HTTP side without a browser (empty folder with one test file and an empty vitest.config.js; vitest 5.0.0 + @vitest/ui 5.0.0 installed):
// probe.mjs — same spawn args and probe as the launcher
import { spawn } from 'node:child_process'
const port = 43217
const cp = spawn(process.execPath, ['node_modules/vitest/vitest.mjs', '--ui', '--no-open', '--watch', '--api.port', String(port)], { stdio: 'pipe' })
let out = ''
cp.stdout.on('data', d => { out += d })
let res
for (let i = 0; i < 100 && !res; i++)
res = await fetch(`http://localhost:${port}/__vitest__/`, { redirect: 'manual' }).catch(() => new Promise(r => setTimeout(r, 300)))
console.log('bare URL ->', res.status, (await res.text()).slice(0, 60), '| launcher accepts:', res.status < 500)
await new Promise(r => setTimeout(r, 1500))
const url = out.replace(/\x1B\[[0-9;]*m/g, '').match(/UI started at (\S+)/)[1]
const r2 = await fetch(url, { redirect: 'manual' })
console.log('token URL ->', r2.status, r2.headers.get('location'), r2.headers.get('set-cookie')?.split(';').slice(1).join(';'))
cp.kill()Output:
bare URL -> 403 Vitest UI requires authentication. Open the URL with the | launcher accepts: true
token URL -> 302 /__vitest__/ Path=/__vitest__/; HttpOnly; SameSite=Strict
Expected: the dock iframe shows the Vitest UI.
Actual: the dock iframe shows Vitest's 403 "requires authentication" page, and the launcher reports the server as ready.
System Info
OS: Windows 11 Pro 10.0.26200 (x64)
Node: 24.21.0
pnpm: 12.5.1
Browser: Chrome
@vitejs/devtools / @vitejs/devtools-kit / @vitejs/devtools-vitest: 0.7.5 (also upstream main ad2d6df)
devframe / @devframes/hub: 1.0.0
vite: 8.3.0
vitest / @vitest/ui: 5.0.0Used Package Manager
pnpm
Validations
- Follow our Code of Conduct
- Read the Contributing Guide.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
- The provided reproduction is a minimal reproducible of the bug.
Activity