{"record":{"id":"c81d94bb13ae2ebd","repo":"apify/crawlee","slug":"the-gotooptions-property-is-not-available-until","errorCode":null,"errorMessage":"The `gotoOptions` property is not available until `prepareNavigation` runs.","messagePattern":"The `gotoOptions` property is not available until `prepareNavigation` runs\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-crawler/src/internals/browser-crawler.ts","lineNumber":611,"sourceCode":"        const addRequests = crawlingContext.addRequests;\n\n        const extractLinks = async (options?: ExtractLinksOptions): Promise<string[]> => {\n            return extractUrlsFromPage(\n                page as any,\n                options?.selector ?? 'a',\n                options?.baseUrl ?? crawlingContext.request.loadedUrl ?? crawlingContext.request.url,\n            );\n        };\n\n        return {\n            page,\n            get response(): Response {\n                throw new Error(\n                    \"The `response` property is not available. This might mean that you're trying to access it before navigation or that navigation resulted in `null` (this should only happen with `about:` URLs)\",\n                );\n            },\n            get gotoOptions(): Dictionary {\n                throw new Error('The `gotoOptions` property is not available until `prepareNavigation` runs.');\n            },\n            extractLinks,\n            enqueueLinks: async (options: EnqueueLinksOptions = {}) => {\n                const baseUrl = resolveBaseUrlForEnqueueLinksFiltering({\n                    enqueueStrategy: options.strategy,\n                    finalRequestUrl: crawlingContext.request.loadedUrl,\n                    originalRequestUrl: crawlingContext.request.url,\n                    userProvidedBaseUrl: options.baseUrl,\n                });\n\n                const urls = await extractLinks(options);\n\n                return addRequests(urls, {\n                    ...options,\n                    baseUrl,\n                    strategy: options.strategy ?? EnqueueStrategy.SameHostname,\n                });\n            },","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/browser-crawler/src/internals/browser-crawler.ts#L593-L629","documentation":"The `gotoOptions` object is produced by the prepareNavigation middleware. Before that middleware runs, the property exists only as a throwing getter to catch premature access, so reading it earlier fails with this error.","triggerScenarios":"Reading crawlingContext.gotoOptions in code that executes before prepareNavigation (pre-navigation hooks, context construction, custom middlewares registered before navigation).","commonSituations":"Custom browser-crawler middlewares inspecting gotoOptions; users hooking into the crawling context before navigation to modify goto options (they should use the prepareNavigation phase instead).","solutions":["Read gotoOptions only after the prepareNavigation middleware has run","To customize navigation, wrap/extend prepareNavigation or use the appropriate hook rather than reading early","Guard access with a try/catch or property check if the timing is uncertain"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"let gotoOptions: Dictionary | undefined;\ntry { gotoOptions = ctx.gotoOptions; } catch { /* prepareNavigation has not run yet */ }","preventionTips":["Read gotoOptions only after the prepareNavigation phase","Modify navigation via the proper hook/middleware, not by early reads"],"tags":["lifecycle","browser","navigation"],"backgroundTag":"property-not-available-yet","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}