apify/crawlee · error · Error

Recoverable state has not yet been loaded - call initialize(

Error message

Recoverable state has not yet been loaded - call initialize() or reset() first

What it means

RecoverableState.currentValue throws until the internal state has been established. State is established either by awaiting initialize() or by calling the synchronous reset(). The getter refuses to return null/unloaded state so callers never silently read an undefined model.

Source

Thrown at packages/core/src/recoverable_state.ts:261

        if (!this.#persistenceEnabled) {
            return;
        }

        serviceLocator.getEventManager().off(EventType.PERSIST_STATE, this.#persistStateQuietly);
        this.#listening = false;
        await this.#persistStateQuietly();
    }

    /**
     * Get the current state.
     *
     * Throws until the state has been established, by either {@apilink RecoverableState.initialize} or the
     * synchronous {@apilink RecoverableState.reset} - the latter being how a caller that cannot await in its
     * constructor gets a usable state right away.
     */
    get currentValue(): TStateModel {
        if (this.#state === null) {
            throw new Error('Recoverable state has not yet been loaded - call initialize() or reset() first');
        }

        return this.#state;
    }

    /**
     * Reset the in-memory state to the default values, leaving any persisted record alone.
     *
     * Use {@apilink RecoverableState.resetStore} to clear the persisted record as well.
     */
    reset(): void {
        this.#state = this.#defaultState();
    }

    /**
     * Clear the persisted state record, leaving the in-memory state alone.
     *
     * This is a between-lifecycles operation - its point is to stop the next {@apilink RecoverableState.initialize}

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. await recoverableState.initialize() before reading currentValue
  2. Call reset() synchronously right after construction if you need a usable state immediately
  3. Gate state reads behind an initialization promise/flag
  4. Move dependent logic into initialize().then(...) or after the await

Example fix

// before
const rs = new RecoverableState({ ... });
console.log(rs.currentValue);
// after
const rs = new RecoverableState({ ... });
await rs.initialize();
console.log(rs.currentValue);
Defensive patterns

Strategy: try-catch

Validate before calling

if (state.isLoaded /* or track initialization yourself */) {
  const value = state.currentValue;
}

Type guard

function isReady<T>(rs: RecoverableState<T>, inited: boolean): rs is RecoverableState<T> & { currentValue: T } { return inited; }

Try / catch

try {
  return state.currentValue;
} catch (err) {
  if (err.message.includes('not yet been loaded')) {
    await state.initialize();
    return state.currentValue;
  }
  throw err;
}

Prevention

When it happens

Trigger: Accessing .currentValue after construction but before the initialize() promise resolves, and without calling reset() first — typically in a constructor that cannot await.

Common situations: Reading state in a class constructor that creates a RecoverableState and initialize() is still pending; event handlers firing before initialization completes; forgetting to await initialize() in an async bootstrap.

Related errors


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