apify/crawlee · error · Error

OwnedOrInjected value is not initialized yet

Error message

OwnedOrInjected value is not initialized yet

What it means

OwnedOrInjected is a slot that either owns a lazily-created default or holds an injected instance. Its `value` getter is strict: if the slot has not been filled yet (neither set() called nor an instance injected), it throws instead of returning undefined. Callers that can tolerate an empty slot must use `maybeValue`.

Source

Thrown at packages/core/src/owned_or_injected.ts:70

    get isOwned(): boolean {
        return this.#owned;
    }

    /**
     * Whether a value is currently available. `false` for an owned slot whose default hasn't been built yet
     * (e.g. a lazily-opened request queue before its first use).
     */
    get isPresent(): boolean {
        return this.#present;
    }

    /**
     * The resolved instance, typed as the public `Injected` type. Throws if the value is not present yet — callers that
     * expect a lazily-filled owned slot should read {@apilink OwnedOrInjected.maybeValue|`maybeValue`} instead.
     */
    get value(): Injected {
        if (!this.#present) {
            throw new Error('OwnedOrInjected value is not initialized yet');
        }

        return this.#value as Injected;
    }

    /**
     * The resolved instance, or `undefined` when a lazily-filled owned slot hasn't been built yet. The non-throwing
     * counterpart to {@apilink OwnedOrInjected.value|`value`} — pairs naturally with `?? fallback` so callers can read
     * a possibly-empty slot without the `isPresent ? value : …` dance.
     */
    get maybeValue(): Injected | undefined {
        return this.#present ? (this.#value as Injected) : undefined;
    }

    /**
     * Fills the (owned) slot with the crawler-built default, returning it for convenience. Only valid on an owned,
     * not-yet-filled slot: borrowed instances are never replaced and an owned slot is filled exactly once (re-setting
     * would silently orphan the previous instance's lifecycle).

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Ensure the owning component's initialization (set()/lazy creation) runs before reading `.value`.
  2. Inject the expected instance explicitly via the options/configuration path that fills the slot.
  3. Use `maybeValue` and handle null when the slot may legitimately be empty.
  4. Move the read after the async initialization point (e.g. after crawler run setup).

Example fix

// before
const client = this.proxyConfigurationSlot.value; // throws if not yet filled
// after
const client = this.proxyConfigurationSlot.maybeValue ?? await this.createDefaultClient();
Defensive patterns

Strategy: type-guard

Validate before calling

if (slot.maybeValue == null) {
  throw new Error('Slot not initialized; ensure init ran before use');
}
const client = slot.value;

Type guard

function isInitialized<TOwned, TInjected>(slot: OwnedOrInjected<TOwned, TInjected>): boolean {
  return slot.maybeValue != null;
}

Try / catch

let client;
try {
  client = slot.value;
} catch (err) {
  if ((err as Error).message === 'OwnedOrInjected value is not initialized yet') {
    client = slot.maybeValue ?? await initializeDefault();
  } else throw err;
}

Prevention

When it happens

Trigger: Reading `.value` on an OwnedOrInjected before initialization — i.e. before the owning component ran set() and before any instance was injected via options/configuration.

Common situations: Accessing a crawler sub-client (e.g. a storage client slot) during construction before lazy init; reading `.value` in a getter that runs earlier than the fill logic; forgetting to pass the injected dependency so the owned default was never created.

Related errors


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