{"record":{"id":"f94bf48f4f8e95a1","repo":"TryGhost/Ghost","slug":"e2e-fixture-failed-to-initialize-per-file-ghost","errorCode":null,"errorMessage":"[e2e fixture] Failed to initialize per-file Ghost instance.","messagePattern":"\\[e2e fixture\\] Failed to initialize per-file Ghost instance\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"e2e/helpers/playwright/fixture.ts","lineNumber":399,"sourceCode":"                config: mergedConfig,\n                stripe\n            });\n            cachedPerFileInstance = {\n                suiteKey,\n                environmentSignature,\n                instance: nextPerFileInstance\n            };\n            cachedPerFileGhostAccountOwner = null;\n            cachedPerFileAuthenticatedSession = null;\n\n            if (previousPerFileInstance) {\n                await environmentManager.perTestTeardown(previousPerFileInstance);\n            }\n        }\n\n        const activePerFileInstance = cachedPerFileInstance;\n        if (!activePerFileInstance) {\n            throw new Error('[e2e fixture] Failed to initialize per-file Ghost instance.');\n        }\n\n        const holder = {...activePerFileInstance.instance};\n        const cycle = async () => {\n            const previousInstance = cachedPerFileInstance?.instance;\n            const nextInstance = await environmentManager.perTestSetup({\n                config: mergedConfig,\n                stripe\n            });\n\n            if (previousInstance) {\n                await environmentManager.perTestTeardown(previousInstance);\n            }\n\n            cachedPerFileInstance = {\n                suiteKey,\n                environmentSignature,\n                instance: nextInstance","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/e2e/helpers/playwright/fixture.ts#L381-L417","documentation":"In per-file isolation, the fixture caches a Ghost instance (cachedPerFileInstance) and recycles it across files. If after the recycle logic activePerFileInstance is still falsy, setup never produced an instance — perFileSetup returned null/undefined or threw silently upstream and the cache stayed empty. The fixture cannot hand a null instance to tests.","triggerScenarios":"environmentManager.perFileSetup returned a falsy instance (no error thrown). An earlier branch skipped instance creation. A previous perTestTeardown nulled the cache and the subsequent setup didn't repopulate. Misconfigured isolation mode resolved to per-file but the manager can't serve it.","commonSituations":"Environment manager implementation gap for per-file mode; setup partially failed and returned null instead of throwing; fixture conditionals (e.g. stripe flag) routed away from instance creation.","solutions":["Inspect why perFileSetup returned falsy — add logging around environmentManager.perFileSetup to see its return value and any swallowed error.","Ensure perFileSetup throws on real failure rather than returning null, so the root cause surfaces.","Confirm isolation mode (per-file) is supported by the active environment manager.","Check the stripe/config branch didn't skip instance creation for this file."],"exampleFix":"// before\nconst activePerFileInstance = cachedPerFileInstance;\nif (!activePerFileInstance) {\n    throw new Error('[e2e fixture] Failed to initialize per-file Ghost instance.');\n}\n\n// after\nconst activePerFileInstance = cachedPerFileInstance;\nif (!activePerFileInstance) {\n    throw new Error(`[e2e fixture] per-file Ghost instance is null after setup (isolation=${resolvedIsolation}, stripe=${stripe}); see preceding perFileSetup logs`);\n}","handlingStrategy":"validation","validationCode":"const inst = await environmentManager.perFileSetup({config: mergedConfig, stripe});\nif (!inst?.instance) {\n    throw new Error('perFileSetup returned no instance — setup failed');\n}","typeGuard":"function isPerFileInstance(x: unknown): x is {instance: GhostInstance} {\n    return typeof x === 'object' && x !== null && 'instance' in x && x.instance != null;\n}","tryCatchPattern":"try {\n    cachedPerFileInstance = await environmentManager.perFileSetup({config: mergedConfig, stripe});\n} catch (e) {\n    throw new Error('[e2e fixture] per-file setup threw', {cause: e});\n}\nif (!cachedPerFileInstance?.instance) {\n    throw new Error('[e2e fixture] per-file setup returned no instance');\n}","preventionTips":["Make perFileSetup throw on failure instead of returning null so the root cause surfaces.","Log perFileSetup return values during fixture bring-up to detect partial failures.","Confirm the environment manager supports the resolved isolation mode."],"tags":["e2e","fixture","isolation","per-file","lifecycle"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}