TryGhost/Ghost · error · Error

Ghost container not initialized

Error message

Ghost container not initialized

What it means

restartWithDatabase() requires a live Ghost container but throws if this.ghostContainer is null/undefined. This container is created during setup (createGhostContainer + start) and stored on the manager. Reaching this throw means setup either never ran, failed before assignment, or a prior teardown nulled the reference. The method swaps the database by removing and recreating the container, so it cannot proceed without a baseline container.

Source

Thrown at e2e/helpers/environment/service-managers/ghost-manager.ts:226

    /**
     * Bring up the egress-monitoring DNS sidecar for this worker (idempotent).
     * Never throws — monitoring is best-effort and must not break the suite.
     */
    private async startEgressMonitor(): Promise<void> {
        if (!EGRESS_MONITOR_ENABLED || this.egressMonitor) {
            return;
        }
        const monitor = new EgressMonitor(this.docker, {
            workerIndex: this.config.workerIndex
        });
        await monitor.start();
        this.egressMonitor = monitor;
    }

    async restartWithDatabase(databaseName: string, extraConfig?: GhostEnvOverrides): Promise<void> {
        if (!this.ghostContainer) {
            throw new Error('Ghost container not initialized');
        }

        debug('Restarting Ghost with database:', databaseName);

        const info = await this.ghostContainer.inspect();
        const containerName = info.Name.replace(/^\//, '');

        // Remove old and create new with updated database
        await this.removeContainer(this.ghostContainer);
        this.ghostContainer = await this.createGhostContainer(containerName, databaseName, extraConfig);
        await this.ghostContainer.start();

        debug('Ghost restarted with database:', databaseName);
    }

    /**
     * Wait for Ghost to become reachable through the same gateway path used by tests.
     */

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Ensure the Ghost instance fixture (ghostInstance) is resolved before any code path that calls restartWithDatabase().
  2. Verify setup completed: assert manager.ghostContainer is set before calling restart helpers, and surface the real setup failure if it isn't.
  3. If teardown nulls the container, re-create via createGhostContainer before calling restartWithDatabase().

Example fix

// before
await ghostManager.restartWithDatabase('ghost_testing');

// after
if (!ghostManager.ghostContainer) {
    throw new Error('restartWithDatabase called before Ghost container was created');
}
await ghostManager.restartWithDatabase('ghost_testing');
Defensive patterns

Strategy: validation

Validate before calling

function assertGhostReady(manager: GhostManager): void {
    if (!manager.ghostContainer) {
        throw new Error('restartWithDatabase called before Ghost container was created');
    }
}

Type guard

function ghostContainerReady(manager: GhostManager): manager is GhostManager & {ghostContainer: Container} {
    return manager.ghostContainer != null;
}

Prevention

When it happens

Trigger: Calling restartWithDatabase() before perTestSetup/instance initialization completed. A previous removeContainer() set this.ghostContainer = null but no new container was assigned. Test fixture ordering invoked a database-swap path before the Ghost fixture resolved.

Common situations: Custom test fixtures that orchestrate database swaps out of order; setup threw partway and left the manager in a half-initialized state; teardown ran in a beforeEach but setup didn't re-run.

Related errors


AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13). Data as JSON: /api/errors/1a9e827eeb8675b6. Report an issue: GitHub.