TryGhost/Ghost · error · Error

Build gateway image not found: ${BUILD_GATEWAY_IMAGE}\n\nTo

Error message

Build gateway image not found: ${BUILD_GATEWAY_IMAGE}\n\nTo fix this, either:\n  1. Pull gateway image: docker pull ${BUILD_GATEWAY_IMAGE}\n  2. Use a different gateway image: GHOST_E2E_MODE=build GHOST_E2E_GATEWAY_IMAGE=<image> pnpm --filter @tryghost/e2e test

What it means

Companion to error 101: after the main Ghost build image is verified, verifyBuildImageExists() separately inspects BUILD_GATEWAY_IMAGE (the traffic-routing gateway container image, e.g. nginx/traefik fronting Ghost). Inspect rejection throws with gateway-specific remediation. Only fires in build mode. Shares the same verifiedBuildImageKey cache, so it runs once per process per image pair.

Source

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

        } catch {
            throw new Error(
                `Build image not found: ${BUILD_IMAGE}\n\n` +
                `You are running in "build" mode, which requires a pre-built Docker image.\n` +
                `For local development, "dev" mode is recommended instead.\n\n` +
                `To fix this, either:\n` +
                `  1. (Recommended) Run "pnpm dev" first, then re-run tests — dev mode is auto-detected and doesn't need this image\n` +
                `  2. Build locally: pnpm --filter @tryghost/e2e build:docker (with GHOST_E2E_BASE_IMAGE set)\n` +
                `  3. Pull from registry: docker pull ${BUILD_IMAGE}\n` +
                `  4. Use a different image: GHOST_E2E_MODE=build GHOST_E2E_IMAGE=<image> pnpm --filter @tryghost/e2e test`
            );
        }

        try {
            const gatewayImage = this.docker.getImage(BUILD_GATEWAY_IMAGE);
            await gatewayImage.inspect();
            debug(`Build gateway image verified: ${BUILD_GATEWAY_IMAGE}`);
        } catch {
            throw new Error(
                `Build gateway image not found: ${BUILD_GATEWAY_IMAGE}\n\n` +
                `To fix this, either:\n` +
                `  1. Pull gateway image: docker pull ${BUILD_GATEWAY_IMAGE}\n` +
                `  2. Use a different gateway image: GHOST_E2E_MODE=build GHOST_E2E_GATEWAY_IMAGE=<image> pnpm --filter @tryghost/e2e test`
            );
        }

        GhostManager.verifiedBuildImageKey = buildImageKey;
    }

    /**
     * Get existing container if running, otherwise create new one.
     * This handles Playwright respawning processes after test failures.
     */
    private async getOrCreateContainer(name: string, create: () => Promise<Container>): Promise<Container> {
        try {
            const existing = this.docker.getContainer(name);
            const info = await existing.inspect();

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Pull the gateway image: docker pull ${BUILD_GATEWAY_IMAGE}.
  2. Point at a different gateway image: GHOST_E2E_MODE=build GHOST_E2E_GATEWAY_IMAGE=<image> pnpm --filter @tryghost/e2e test.
  3. Confirm the tag matches what the build pipeline pushes; add the gateway image to CI's docker-pull step alongside BUILD_IMAGE.

Example fix

# before
GHOST_E2E_MODE=build pnpm --filter @tryghost/e2e test

# after
docker pull ${BUILD_GATEWAY_IMAGE} && GHOST_E2E_MODE=build pnpm --filter @tryghost/e2e test
Defensive patterns

Strategy: validation

Validate before calling

async function gatewayImageExists(): Promise<boolean> {
    try { await new Docker().getImage(BUILD_GATEWAY_IMAGE).inspect(); return true; }
    catch { return false; }
}
if (GHOST_E2E_MODE === 'build' && !await gatewayImageExists()) {
    throw new Error(`Pre-flight: gateway image ${BUILD_GATEWAY_IMAGE} missing. docker pull it.`);
}

Prevention

When it happens

Trigger: BUILD_GATEWAY_IMAGE (from GHOST_E2E_GATEWAY_IMAGE) is absent locally. The main image exists but the gateway image was never pulled/built. Gateway tag was changed via env without re-pulling. Different registry/source than the Ghost image so a single pull doesn't cover both.

Common situations: Hardened CI that caches the Ghost image but not the gateway image; switching gateway variants; new contributor running build mode who only pulled the Ghost image.

Related errors


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