apify/crawlee · error · Error

Remote browser endpoint resolved to an empty string.

Error message

Remote browser endpoint resolved to an empty string.

What it means

RemoteBrowserPool accepts an endpoint either as a string or a function returning a string/object. When the endpoint is a function, it is awaited and the result validated; if it resolves to an empty string the pool cannot connect, so it throws with this message. It guards against silent misconfiguration producing empty endpoint values.

Source

Thrown at packages/browser-pool/src/remote-browser-pool.ts:78

    readonly #onRelease: ((info: { endpoint: string; context?: Record<string, unknown> }) => unknown) | undefined;
    readonly #log: CrawleeLogger;

    constructor(
        endpoint: RemoteBrowserEndpoint,
        onRelease: ((info: { endpoint: string; context?: Record<string, unknown> }) => unknown) | undefined,
        log: CrawleeLogger,
    ) {
        this.#endpoint = endpoint;
        this.#onRelease = onRelease;
        this.#log = log;
    }

    async resolve(options?: { proxyUrl?: string }): Promise<{ url: string; token: number }> {
        const resolved = typeof this.#endpoint === 'function' ? await this.#endpoint(options) : this.#endpoint;

        let result: ResolvedRemoteEndpoint;
        if (typeof resolved === 'string') {
            if (!resolved) throw new Error('Remote browser endpoint resolved to an empty string.');
            result = { url: resolved };
        } else if (!resolved?.url) {
            throw new Error("Remote browser endpoint() must return a URL string or an object with a non-empty 'url'.");
        } else {
            result = resolved;
        }

        const token = this.#nextToken++;
        this.#sessions.set(token, { url: result.url, context: result.context, released: false });
        return { url: result.url, token };
    }

    async release(token: number): Promise<void> {
        const session = this.#sessions.get(token);
        // Release at most once per session — guards a close()/teardown race (the `released` flag is set
        // synchronously before the awaited onRelease, so releaseAll() can't double-fire an in-flight release).
        if (!session || session.released) return;
        session.released = true;

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Fix the endpoint function to return a valid ws/http URL; check the source (env var, config, API) for the empty value.
  2. Add a default/fallback or fail fast at startup: throw early if the configured endpoint is empty.
  3. Log the resolved value before returning it from the endpoint function to catch empty resolutions during development.

Example fix

// before
new RemoteBrowserPool({ endpoint: async () => process.env.REMOTE_BROWSER_URL ?? '' });
// after
new RemoteBrowserPool({
  endpoint: async () => {
    const url = process.env.REMOTE_BROWSER_URL;
    if (!url) throw new Error('REMOTE_BROWSER_URL is not set');
    return url;
  },
});
Defensive patterns

Strategy: validation

Validate before calling

const resolved = await endpointFn();
if (typeof resolved === 'string' && !resolved) {
  throw new Error('Remote browser endpoint is empty; check env/config before pool init');
}

Type guard

function isNonEmptyString(v: unknown): v is string {
  return typeof v === 'string' && v.length > 0;
}

Try / catch

try {
  await remotePool.init();
} catch (err) {
  if (err instanceof Error && err.message.includes('resolved to an empty string')) {
    // re-read env/config or retry provisioning, then re-init
  } throw err;
}

Prevention

When it happens

Trigger: Providing a function endpoint to RemoteBrowserPool (or the pool config) that returns '' — e.g. an env var that is unset, an API returning an empty url field, or template interpolation of a missing value.

Common situations: REMOTE_BROWSER_URL environment variable missing/empty in CI or containers; a provisioning endpoint returning an empty body parsed to ''; race where the browser server hasn't published its URL yet.

Related errors


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/c00c94c09aca1710. Report an issue: GitHub.