TryGhost/Ghost · error · Error

baseURL is not defined

Error message

baseURL is not defined

What it means

The ghostAccountOwner fixture asserts ghostInstance.baseUrl is truthy before creating the test owner. A falsy baseUrl means the Ghost instance fixture didn't produce a URL — setup didn't run, failed, or the instance is in a state where no gateway URL was assigned. This guard fails fast rather than passing undefined into User creation/API calls.

Source

Thrown at e2e/helpers/playwright/fixture.ts:543

        if (!stripeEnabled || !baseURL || !stripeServer) {
            await use(undefined);
            return;
        }

        const webhookClient = new WebhookClient(baseURL);
        const service = new StripeTestService(stripeServer, webhookClient);
        await use(service);
    },

    baseURL: async ({ghostInstance, _testEnvironmentContext}, use) => {
        _testEnvironmentContext.markResetEnvironmentBlocker('baseURL');
        await use(ghostInstance.baseUrl);
    },

    // Create user credentials only (no authentication)
    ghostAccountOwner: async ({ghostInstance, _testEnvironmentContext}, use) => {
        if (!ghostInstance.baseUrl) {
            throw new Error('baseURL is not defined');
        }

        _testEnvironmentContext.markResetEnvironmentBlocker('ghostAccountOwner');

        if (_testEnvironmentContext.resolvedIsolation === 'per-file' && cachedPerFileGhostAccountOwner) {
            await use(cachedPerFileGhostAccountOwner);
            return;
        }

        // Create user in this Ghost instance
        const ghostAccountOwner: User = {
            name: 'Test User',
            email: `test${faker.string.uuid()}@ghost.org`,
            password: 'test@123@test'
        };
        await setupUser(ghostInstance.baseUrl, ghostAccountOwner);

        if (_testEnvironmentContext.resolvedIsolation === 'per-file') {

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Ensure the ghostInstance fixture fully completes (container + gateway ready) before ghostAccountOwner is used — check waitForReady ran.
  2. Log ghostInstance in the fixture to see what baseUrl (and the rest) actually resolved to.
  3. Make instance setup throw (rather than return a baseUrl-less object) so the real failure surfaces earlier.
  4. Confirm the gateway port assignment path (getGatewayPort) ran during setup.

Example fix

// before
if (!ghostInstance.baseUrl) {
    throw new Error('baseURL is not defined');
}

// after
if (!ghostInstance.baseUrl) {
    throw new Error(`baseURL is not defined (instance state: ${JSON.stringify({running: !!ghostInstance.container, port: ghostInstance.port})})`);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!ghostInstance.baseUrl) {
    throw new Error(`ghostInstance.baseUrl missing (setup incomplete: ${JSON.stringify({container: !!ghostInstance.container})})`);
}

Type guard

function instanceHasBaseUrl(i: GhostInstance): i is GhostInstance & {baseUrl: string} {
    return typeof i.baseUrl === 'string' && i.baseUrl.length > 0;
}

Prevention

When it happens

Trigger: ghostInstance fixture resolved but baseUrl is empty (instance not started, gateway port not assigned). Fixture ordering pulled ghostAccountOwner without ghostInstance completing properly. Instance creation returned an object lacking baseUrl.

Common situations: Setup failed silently and returned a partial instance; gateway never came up so baseUrl wasn't set; fixture misconfiguration where ghostAccountOwner is requested without the ghost instance being ready.

Related errors


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