{"record":{"id":"2f5d806703e9c1ce","repo":"jackwener/OpenCLI","slug":"youdao-note-extractor-failed-error-instanceof-e","errorCode":null,"errorMessage":"Youdao note extractor failed: ${error instanceof Error ? error.message : String(error)}","messagePattern":"Youdao note extractor failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/youdao/note.js","lineNumber":246,"sourceCode":"  columns: ['title', 'content', 'summary', 'keywords', 'created_at', 'file_size', 'url'],\n  func: async function(page, kwargs) {\n    const url = normalizeShareUrl(kwargs.url);\n    try {\n      await page.goto(url);\n    } catch (error) {\n      throw new CommandExecutionError(`Failed to open Youdao Note URL: ${error instanceof Error ? error.message : String(error)}`);\n    }\n    try {\n      await page.wait({ selector: '#root, .file-name, body', timeout: 10 });\n    } catch {\n      await page.wait(3).catch(function() {});\n    }\n    await page.wait(2).catch(function() {});\n    let payload;\n    try {\n      payload = await page.evaluate(buildExtractorJs());\n    } catch (error) {\n      throw new CommandExecutionError(`Youdao note extractor failed: ${error instanceof Error ? error.message : String(error)}`);\n    }\n    return [normalizeExtractionResult(payload, url)];\n  },\n});\n\nexport var __test__ = {\n  buildExtractorJs: buildExtractorJs,\n  command: command,\n  formatYoudaoTimestamp: formatYoudaoTimestamp,\n  normalizeExtractionResult: normalizeExtractionResult,\n  normalizeShareUrl: normalizeShareUrl,\n};\n","sourceCodeStart":228,"sourceCodeEnd":259,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youdao/note.js#L228-L259","documentation":"page.evaluate(buildExtractorJs()) executes the injected extractor script in the page; any exception it throws (or a broken evaluate bridge) is rethrown as 'Youdao note extractor failed: <msg>'. The wrapper preserves the underlying error message from the browser context.","triggerScenarios":"The injected script throws inside the page: expected store object absent, null dereference on missing DOM nodes, JSON serialization issues, or page context destroyed by navigation/redirect mid-evaluate.","commonSituations":"Youdao page changed structure after a site update; evaluate ran before SPA mount; page navigated away during extraction (login redirect); very large payload breaking the evaluate bridge.","solutions":["Read the wrapped cause message to see what failed inside the page","Re-run after the page settles; ensure no concurrent navigation occurs during evaluate","Update buildExtractorJs for the current Youdao DOM/store layout","Add defensive null checks inside the extractor script for every store/DOM lookup"],"exampleFix":"// before\nconst store = window.__INITIAL_STATE__.note;\n// after\nconst store = (window.__INITIAL_STATE__ && window.__INITIAL_STATE__.note) || null;\nif (!store) return null; // normalization will report the missing fields","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isExtractionFailure(e) {\n  return e instanceof Error && /^Youdao note extractor failed: /.test(e.message);\n}","tryCatchPattern":"try {\n  await cli.youdao.note({ url });\n} catch (e) {\n  if (/Youdao note extractor failed: (.+)/.test(e.message)) {\n    const cause = e.message.match(/Youdao note extractor failed: (.+)/)[1];\n    console.error('In-page extractor error:', cause);\n  } else throw e;\n}","preventionTips":["Keep buildExtractorJs defensive (null-check every store/DOM access)","Avoid navigating the page during evaluate","Pin/monitor Youdao frontend changes; smoke-test the extractor regularly","Return null from the extractor instead of throwing for missing data"],"tags":["browser-automation","javascript","extraction"],"backgroundTag":"in-page-script-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}