{"record":{"id":"74c06eec3ed7a587","repo":"jackwener/OpenCLI","slug":"youdao-note-url-cannot-be-empty","errorCode":null,"errorMessage":"youdao note url cannot be empty","messagePattern":"youdao note url cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/youdao/note.js","lineNumber":21,"sourceCode":"\nconst ALLOWED_HOSTS = new Set([\n  'share.note.youdao.com',\n  'note.youdao.com',\n  'share.note.youdao.cn',\n  'note.youdao.cn',\n]);\n\nfunction unwrapEvaluateResult(payload) {\n  if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {\n    return payload.data;\n  }\n  return payload;\n}\n\nfunction normalizeShareUrl(raw) {\n  const value = String(raw ?? '').trim();\n  if (!value) {\n    throw new ArgumentError('youdao note url cannot be empty', 'Pass a full public share URL from Youdao Notes.');\n  }\n  let parsed;\n  try {\n    parsed = new URL(value);\n  } catch {\n    throw new ArgumentError('Invalid Youdao Note URL', 'Example: https://share.note.youdao.com/ynoteshare/index.html?id=...&type=note');\n  }\n  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n    throw new ArgumentError('Youdao Note URL must use http or https');\n  }\n  if (!ALLOWED_HOSTS.has(parsed.hostname)) {\n    throw new ArgumentError('Youdao Note URL must be under note.youdao.com or note.youdao.cn');\n  }\n  if (!parsed.searchParams.get('id')) {\n    throw new ArgumentError('Youdao Note URL must include an id query parameter');\n  }\n  const type = parsed.searchParams.get('type');\n  if (type && type !== 'note') {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youdao/note.js#L3-L39","documentation":"ArgumentError thrown by normalizeShareUrl when the positional `url` argument is empty, null, undefined, or whitespace-only. The library requires a full Youdao share URL to load in a headless browser; without it there is nothing to fetch. This is an upfront input validation so the failure happens before any browser work.","triggerScenarios":"Calling `youdao note` (or command.func) with an empty/missing positional url argument, e.g. `youdao note ''`, `youdao note '   '`, or a kwargs object where kwargs.url is undefined or null.","commonSituations":"CLI invocations where the URL was stored in a shell variable that expanded to empty; scripts piping config values that are missing; automation passing undefined because a prior parsing step failed; users pasting only a note ID instead of the full share URL.","solutions":["Pass the complete public share URL, e.g. https://share.note.youdao.com/ynoteshare/index.html?id=<id>&type=note","Check the shell variable/config key holding the URL actually has a non-empty value before invoking","If you only have the note ID, build the URL: `https://share.note.youdao.com/ynoteshare/index.html?id=${id}&type=note`"],"exampleFix":"// before\nawait run(['youdao', 'note', urlFromConfig]);\n// after\nif (!urlFromConfig || !urlFromConfig.trim()) {\n  throw new Error('config missing youdao share url');\n}\nawait run(['youdao', 'note', urlFromConfig.trim()]);","handlingStrategy":"validation","validationCode":"function hasShareUrl(u) {\n  return typeof u === 'string' && u.trim().length > 0;\n}\nif (!hasShareUrl(inputUrl)) throw new Error('provide a youdao share url first');","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await youdaoNote(url);\n} catch (e) {\n  if (String(e.message).includes('url cannot be empty')) {\n    // prompt user / fix config for the url input\n  } else throw e;\n}","preventionTips":["Validate CLI inputs for non-empty trimmed values before invoking","Fail fast in scripts when a config/env variable holding the URL is empty","Build the full URL from a note id with a helper rather than passing raw ids"],"tags":["argument-error","validation","input-validation","url"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}