{"record":{"id":"1342bcf10c9504ff","repo":"apify/crawlee","slug":"the-document-property-is-not-available-skipna-1342bc","errorCode":null,"errorMessage":"The `document` property is not available - `skipNavigation` was used","messagePattern":"The `document` property is not available - `skipNavigation` was used","errorType":"exception","errorClass":"NavigationSkippedError","httpStatus":null,"severity":"error","filePath":"packages/linkedom-crawler/src/internals/linkedom-crawler.ts","lineNumber":260,"sourceCode":"                },\n            };\n        } catch (err) {\n            if (err instanceof NavigationSkippedError) {\n                return {\n                    get window(): Window {\n                        throw new NavigationSkippedError(\n                            'The `window` property is not available - `skipNavigation` was used',\n                            { cause: err },\n                        );\n                    },\n                    get body(): string {\n                        throw new NavigationSkippedError(\n                            'The `body` property is not available - `skipNavigation` was used',\n                            { cause: err },\n                        );\n                    },\n                    get document(): Document {\n                        throw new NavigationSkippedError(\n                            'The `document` property is not available - `skipNavigation` was used',\n                            { cause: err },\n                        );\n                    },\n                };\n            }\n\n            throw err;\n        }\n    }\n\n    private async addHelpers(crawlingContext: InternalHttpCrawlingContext & { body: string; window: Window }) {\n        const addRequests = crawlingContext.addRequests;\n\n        const extractLinks = async (options?: ExtractLinksOptions): Promise<string[]> => {\n            if (!crawlingContext.window) {\n                throw new Error('Cannot extract links because the DOM is not available.');\n            }","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/linkedom-crawler/src/internals/linkedom-crawler.ts#L242-L278","documentation":"Same as the jsdom counterpart: with `skipNavigation` in LinkedomCrawler, `context.document` (normally the linkedom Document) is a getter that throws NavigationSkippedError because no document tree was ever constructed.","triggerScenarios":"Accessing `context.document` (e.g. `context.document.getElementsByTagName(...)`) in a LinkedomCrawler handler while `skipNavigation: true` is active.","commonSituations":"Migrating JSDOMCrawler handlers to LinkedomCrawler without realizing skipNavigation strips document/window/body; postNavigationHooks that query the document.","solutions":["Remove `skipNavigation: true` from the request/crawler options.","Parse `context.body` (raw HTML) with cheerio rather than using document APIs.","Split the crawl: skipNavigation requests for metadata-only, normal requests for DOM parsing.","Add an early check in the handler to throw a clearer domain-specific error when document is unavailable."],"exampleFix":"// before (skipNavigation: true)\nconst headings = [...context.document.querySelectorAll('h2')];\n\n// after\nconst $ = (await import('cheerio')).load(context.body);\nconst headings = $('h2').toArray();","handlingStrategy":"try-catch","validationCode":"if (request.skipNavigation === true) {\n    // context.document will throw; switch to string parsing\n}","typeGuard":"function hasDocument(ctx: object): ctx is { document: Document } {\n    return 'document' in ctx && (ctx as any).document !== undefined;\n}","tryCatchPattern":"try {\n    const text = context.document.body?.textContent;\n    use(text);\n} catch (err) {\n    if ((err as Error).message.includes('`skipNavigation` was used')) {\n        use(cheerio.load(context.body).text());\n    } else {\n        throw err;\n    }\n}","preventionTips":["Disable skipNavigation for handlers that rely on document APIs.","Wrap document access in a utility that falls back to cheerio.","Validate crawl config so document-requiring handlers never get skipNavigation requests.","Catch NavigationSkippedError by name/message in shared helpers."],"tags":["linkedom","skip-navigation","dom","api-misuse"],"backgroundTag":"dom-unavailable-skip-navigation","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}