{"record":{"id":"8cc9344b2ccc9199","repo":"jackwener/OpenCLI","slug":"youdao-note-parser-did-not-extract-a-title","errorCode":null,"errorMessage":"Youdao note parser did not extract a title","messagePattern":"Youdao note parser did not extract a title","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/youdao/note.js","lineNumber":198,"sourceCode":"    if (reason === 'auth') {\n      throw new AuthRequiredError('note.youdao.com', 'Youdao shared note requires login or additional permission');\n    }\n    if (reason === 'not_found') {\n      throw new EmptyResultError('youdao note', 'The shared note is missing, expired, cancelled, or inaccessible.');\n    }\n    throw new CommandExecutionError(`Youdao note parser failed: ${reason}`);\n  }\n  const title = String(data[1] ?? '');\n  const content = String(data[2] ?? '');\n  const summary = String(data[3] ?? '');\n  const keywords = String(data[4] ?? '');\n  const createTime = data[5];\n  const fileSize = data[6];\n  const hasContentField = data[7] === true;\n  const rawContentLength = Number(data[8] ?? 0);\n  const finalUrl = String(data[9] || sourceUrl);\n  if (!title) {\n    throw new CommandExecutionError('Youdao note parser did not extract a title');\n  }\n  if (!hasContentField) {\n    throw new CommandExecutionError('Youdao note parser did not find full note content in the page store');\n  }\n  if (rawContentLength > 0 && !content) {\n    throw new CommandExecutionError('Youdao note parser found note content but extracted no readable text');\n  }\n  const row = {};\n  row.title = title;\n  row.content = content;\n  row.summary = summary;\n  row.keywords = keywords;\n  row.created_at = formatYoudaoTimestamp(createTime);\n  row.file_size = fileSize == null ? '' : String(fileSize);\n  row.url = finalUrl;\n  return row;\n}\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youdao/note.js#L180-L216","documentation":"normalizeExtractionResult validates the payload returned by the in-page Youdao note extractor before building the output row. The page store must supply a note title; if `title` is falsy the result is considered unusable and a CommandExecutionError is thrown rather than emitting a row with an empty title.","triggerScenarios":"The browser-side extractor ran but its payload contained an empty/missing title field — e.g. the shared note page rendered an error/interstitial instead of the note, the extractor's title selectors matched nothing, or the note genuinely has no title and the extractor did not fall back to a default.","commonSituations":"Sharing links that expired or were deleted; scraping before the SPA hydrated the page store; Youdao changed DOM markup so the title selector breaks; region/login wall showing a generic page.","solutions":["Open the URL in a real browser and confirm the note loads and shows a title","Verify the extractor script (buildExtractorJs) still matches Youdao's current DOM/title markup and update selectors","Ensure page.goto + wait completed before evaluate so the page store is populated","Add a fallback title (e.g. first heading or file name) in the extractor payload before normalization"],"exampleFix":"// before\nconst title = payload.title;\n// after\nconst title = payload.title || payload.raw?.fileName || payload.raw?.subject || 'Untitled Youdao note';","handlingStrategy":"validation","validationCode":"if (!payload || payload.title == null || String(payload.title).trim() === '') {\n  throw new Error('Extractor payload has no title; aborting before normalizeExtractionResult');\n}","typeGuard":"function hasTitle(p) {\n  return typeof p === 'object' && p !== null && typeof p.title === 'string' && p.title.trim().length > 0;\n}","tryCatchPattern":"try {\n  const row = await cli.youdao.note({ url });\n} catch (e) {\n  if (/did not extract a title/.test(e.message)) {\n    console.error('Note page did not yield a title; check the URL or update extractor selectors');\n  } else throw e;\n}","preventionTips":["Validate the share URL loads and shows a title in a normal browser first","Keep extractor selectors in sync with Youdao's DOM after site updates","Ensure the page fully hydrates before evaluate","Provide a fallback title in the extractor payload"],"tags":["parsing","browser-automation","extraction"],"backgroundTag":"extracted-field-missing","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}