{"record":{"id":"a3cab9b54df53996","repo":"apify/crawlee","slug":"recoverable-state-has-not-yet-been-loaded-call-i","errorCode":null,"errorMessage":"Recoverable state has not yet been loaded - call initialize() or reset() first","messagePattern":"Recoverable state has not yet been loaded - call initialize\\(\\) or reset\\(\\) first","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/recoverable_state.ts","lineNumber":261,"sourceCode":"        if (!this.#persistenceEnabled) {\n            return;\n        }\n\n        serviceLocator.getEventManager().off(EventType.PERSIST_STATE, this.#persistStateQuietly);\n        this.#listening = false;\n        await this.#persistStateQuietly();\n    }\n\n    /**\n     * Get the current state.\n     *\n     * Throws until the state has been established, by either {@apilink RecoverableState.initialize} or the\n     * synchronous {@apilink RecoverableState.reset} - the latter being how a caller that cannot await in its\n     * constructor gets a usable state right away.\n     */\n    get currentValue(): TStateModel {\n        if (this.#state === null) {\n            throw new Error('Recoverable state has not yet been loaded - call initialize() or reset() first');\n        }\n\n        return this.#state;\n    }\n\n    /**\n     * Reset the in-memory state to the default values, leaving any persisted record alone.\n     *\n     * Use {@apilink RecoverableState.resetStore} to clear the persisted record as well.\n     */\n    reset(): void {\n        this.#state = this.#defaultState();\n    }\n\n    /**\n     * Clear the persisted state record, leaving the in-memory state alone.\n     *\n     * This is a between-lifecycles operation - its point is to stop the next {@apilink RecoverableState.initialize}","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/recoverable_state.ts#L243-L279","documentation":"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.","triggerScenarios":"Accessing .currentValue after construction but before the initialize() promise resolves, and without calling reset() first — typically in a constructor that cannot await.","commonSituations":"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.","solutions":["await recoverableState.initialize() before reading currentValue","Call reset() synchronously right after construction if you need a usable state immediately","Gate state reads behind an initialization promise/flag","Move dependent logic into initialize().then(...) or after the await"],"exampleFix":"// before\nconst rs = new RecoverableState({ ... });\nconsole.log(rs.currentValue);\n// after\nconst rs = new RecoverableState({ ... });\nawait rs.initialize();\nconsole.log(rs.currentValue);","handlingStrategy":"try-catch","validationCode":"if (state.isLoaded /* or track initialization yourself */) {\n  const value = state.currentValue;\n}","typeGuard":"function isReady<T>(rs: RecoverableState<T>, inited: boolean): rs is RecoverableState<T> & { currentValue: T } { return inited; }","tryCatchPattern":"try {\n  return state.currentValue;\n} catch (err) {\n  if (err.message.includes('not yet been loaded')) {\n    await state.initialize();\n    return state.currentValue;\n  }\n  throw err;\n}","preventionTips":["Always await initialize() before any state read","Call reset() in constructors that cannot await","Expose an initialization promise and gate consumers on it","Add an integration test that reads state immediately after construction"],"tags":["lifecycle","state","initialization"],"backgroundTag":"state-not-initialized","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}