TryGhost/Ghost · error · Error
[e2e fixture] resetEnvironment() must be called before resol
Error message
[e2e fixture] resetEnvironment() must be called before resolving "${blocker}". Use it in a beforeEach hook that only depends on resetEnvironment and fixtures that remain valid after a recycle. What it means
resetEnvironment() recycles the Ghost instance but is only valid before stateful fixtures (baseURL, ghostAccountOwner, page) materialize — those capture references invalidated by a recycle. _testEnvironmentContext tracks a 'blocker' (the name of the first materialized stateful fixture); if resetEnvironment() is called after one resolves, it throws naming the blocker. This is a usage-contract violation, not an infrastructure failure.
Source
Thrown at e2e/helpers/playwright/fixture.ts:513
await use(_testEnvironmentContext.holder);
},
resolvedIsolation: async ({_testEnvironmentContext}, use) => {
await use(_testEnvironmentContext.resolvedIsolation);
},
resetEnvironment: async ({_testEnvironmentContext}, use) => {
await use(async () => {
if (_testEnvironmentContext.resolvedIsolation === 'per-test') {
debug('resetEnvironment() is a no-op in per-test isolation mode');
return;
}
// Only support resetEnvironment() before stateful fixtures such as the
// baseURL, authenticated user session, or page have been materialized.
const blocker = _testEnvironmentContext.getResetEnvironmentBlocker();
if (blocker) {
throw new Error(
`[e2e fixture] resetEnvironment() must be called before resolving ` +
`"${blocker}". Use it in a beforeEach hook that only depends on ` +
'resetEnvironment and fixtures that remain valid after a recycle.'
);
}
await _testEnvironmentContext.cycle();
});
},
stripe: async ({stripeEnabled, baseURL, stripeServer}, use) => {
if (!stripeEnabled || !baseURL || !stripeServer) {
await use(undefined);
return;
}
const webhookClient = new WebhookClient(baseURL);
const service = new StripeTestService(stripeServer, webhookClient);View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Move resetEnvironment() into a beforeEach whose only fixture dependencies are resetEnvironment and fixtures valid after a recycle (none of baseURL/page/ghostAccountOwner).
- Split the hook: one beforeEach for resetEnvironment, a separate one (or in-test) for stateful fixtures.
- Use per-test isolation if you need fresh state per test instead of manual resets.
- Read the blocker name in the message to find which fixture was already resolved and remove that dependency from the reset hook.
Example fix
// before
beforeEach(async ({resetEnvironment, baseURL, page}) => {
await resetEnvironment();
await page.goto(baseURL);
});
// after
test.beforeEach(async ({resetEnvironment}) => {
await resetEnvironment();
});
test('...', async ({baseURL, page}) => {
await page.goto(baseURL);
}); Defensive patterns
Strategy: validation
Validate before calling
if (_testEnvironmentContext.getResetEnvironmentBlocker()) {
throw new Error(`resetEnvironment blocked by ${_testEnvironmentContext.getResetEnvironmentBlocker()}`);
} Prevention
- Keep resetEnvironment in a beforeEach that depends only on resetEnvironment (and recycle-safe fixtures).
- Never mix resetEnvironment with baseURL/page/ghostAccountOwner in the same hook.
- Prefer per-test isolation over manual resets when you need fresh state per test.
When it happens
Trigger: A test's beforeEach depends on both resetEnvironment and baseURL/page/authenticated session. resetEnvironment() called inside or after a hook that already pulled baseURL. Fixture dependency graph places resetEnvironment downstream of a stateful fixture.
Common situations: Refactoring tests and adding resetEnvironment() to a beforeEach that already transitively depends on baseURL; mixing per-test resets with per-file isolation incorrectly; copying a hook pattern without checking fixture deps.
Related errors
- [e2e fixture] Failed to initialize per-file Ghost instance.
- baseURL is not defined
- Ghost container not initialized
- Error going to signin page (no response)
- Error going to signin page (${response.status})
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/5492090c7a4957aa.
Report an issue: GitHub.