{"record":{"id":"cbed9cbdbe893864","repo":"apify/crawlee","slug":"ownedorinjected-value-is-already-initialized","errorCode":null,"errorMessage":"OwnedOrInjected value is already initialized","messagePattern":"OwnedOrInjected value is already initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/owned_or_injected.ts","lineNumber":96,"sourceCode":"     * counterpart to {@apilink OwnedOrInjected.value|`value`} — pairs naturally with `?? fallback` so callers can read\n     * a possibly-empty slot without the `isPresent ? value : …` dance.\n     */\n    get maybeValue(): Injected | undefined {\n        return this.#present ? (this.#value as Injected) : undefined;\n    }\n\n    /**\n     * Fills the (owned) slot with the crawler-built default, returning it for convenience. Only valid on an owned,\n     * not-yet-filled slot: borrowed instances are never replaced and an owned slot is filled exactly once (re-setting\n     * would silently orphan the previous instance's lifecycle).\n     */\n    set(value: Owned): Owned {\n        if (!this.#owned) {\n            throw new Error('Cannot set() a borrowed OwnedOrInjected value');\n        }\n\n        if (this.#present) {\n            throw new Error('OwnedOrInjected value is already initialized');\n        }\n\n        this.#value = value;\n        this.#present = true;\n\n        return value;\n    }\n\n    /**\n     * Runs an owned-only lifecycle hook, invoked (with the value typed as the concrete `Owned`) only when the crawler\n     * owns a present instance — a no-op for a borrowed instance or an owned-but-not-yet-built slot.\n     */\n    async ifOwned<R>(fn: (value: Owned) => R | Promise<R>): Promise<R | undefined> {\n        if (!this.#owned || !this.#present) {\n            return undefined;\n        }\n\n        return fn(this.#value as Owned);","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/owned_or_injected.ts#L78-L114","documentation":"set() fills an owned slot exactly once. Calling it a second time would silently orphan the previous instance (leaking its resources and lifecycle), so a re-set on an already-present slot throws.","triggerScenarios":"Calling set() twice on the same owned slot — e.g. lazy-init logic running twice (double crawler init, re-run, or two code paths both calling set()), or calling set() after the slot was already filled.","commonSituations":"Re-running initialization in tests without recreating the crawler; concurrent/overlapping lazy-init paths; accidentally calling set() on a slot already populated by an earlier call.","solutions":["Guard with `if (slot.maybeValue == null) slot.set(x)` so set() runs only once.","Memoize the default instance and reuse it instead of re-invoking the init path.","Create a new OwnedOrInjected slot if you genuinely need a fresh lifecycle.","If a different instance is needed, replace the whole owning object rather than re-setting the slot."],"exampleFix":"// before\nthis.slot.set(buildClient());\n// ...later, same slot\nthis.slot.set(buildClient()); // throws\n// after\nif (this.slot.maybeValue == null) this.slot.set(buildClient());","handlingStrategy":"validation","validationCode":"if (slot.maybeValue == null) {\n  slot.set(buildClient());\n}","typeGuard":"function isUnfilled<TOwned, TInjected>(slot: OwnedOrInjected<TOwned, TInjected>): boolean {\n  return slot.maybeValue == null;\n}","tryCatchPattern":"try {\n  slot.set(buildClient());\n} catch (err) {\n  if ((err as Error).message === 'OwnedOrInjected value is already initialized') {\n    return slot.value; // reuse existing instance\n  }\n  throw err;\n}","preventionTips":["Guard every set() call with a maybeValue == null check.","Make lazy-init idempotent (memoize the built instance).","Avoid initializing the same crawler object twice; recreate it instead.","In tests, build a fresh crawler per test rather than re-running init."],"tags":["lifecycle","initialization","double-initialization"],"backgroundTag":"value-already-initialized","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}