jackwener/OpenCLI · error · ArgumentError

Youdao Note URL must use http or https

Error message

Youdao Note URL must use http or https

What it means

ArgumentError thrown by normalizeShareUrl when the parsed URL uses a protocol other than http: or https: (e.g. javascript:, file:, ftp:, data:). The library loads the URL in a browser page and only permits web schemes for safety and correctness.

Source

Thrown at clis/youdao/note.js:30

  if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {
    return payload.data;
  }
  return payload;
}

function normalizeShareUrl(raw) {
  const value = String(raw ?? '').trim();
  if (!value) {
    throw new ArgumentError('youdao note url cannot be empty', 'Pass a full public share URL from Youdao Notes.');
  }
  let parsed;
  try {
    parsed = new URL(value);
  } catch {
    throw new ArgumentError('Invalid Youdao Note URL', 'Example: https://share.note.youdao.com/ynoteshare/index.html?id=...&type=note');
  }
  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
    throw new ArgumentError('Youdao Note URL must use http or https');
  }
  if (!ALLOWED_HOSTS.has(parsed.hostname)) {
    throw new ArgumentError('Youdao Note URL must be under note.youdao.com or note.youdao.cn');
  }
  if (!parsed.searchParams.get('id')) {
    throw new ArgumentError('Youdao Note URL must include an id query parameter');
  }
  const type = parsed.searchParams.get('type');
  if (type && type !== 'note') {
    throw new ArgumentError('youdao note only accepts shared note URLs', 'Shared notebooks are not implemented yet.');
  }
  return parsed.toString();
}

function formatYoudaoTimestamp(value) {
  if (value == null || value === '') return '';
  const numeric = Number(value);
  if (!Number.isFinite(numeric) || numeric <= 0) return String(value);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use the https form of the share URL: https://share.note.youdao.com/ynoteshare/index.html?id=<id>&type=note
  2. Strip or replace non-http(s) schemes in your input pipeline before calling the command
  3. Verify no prefix like 'javascript:' or 'file:' was accidentally prepended by your code

Example fix

// before
await youdaoNote(`file://${localPath}`);
// after
if (!/^https?:\/\//.test(inputUrl)) throw new Error('need http(s) share URL');
await youdaoNote(inputUrl);
Defensive patterns

Strategy: validation

Validate before calling

function isHttpUrl(u) {
  try { const p = new URL(u); return p.protocol === 'https:' || p.protocol === 'http:'; }
  catch { return false; }
}
if (!isHttpUrl(inputUrl)) throw new Error('share URL must be http(s)');

Type guard

function hasWebProtocol(v) {
  try { const p = new URL(v); return p.protocol === 'https:' || p.protocol === 'http:'; } catch { return false; }
}

Try / catch

try {
  await youdaoNote(url);
} catch (e) {
  if (String(e.message).includes('must use http or https')) {
    // replace file:/javascript:/ftp: source with the public https share URL
  } else throw e;
}

Prevention

When it happens

Trigger: Passing 'javascript:alert(1)', 'file:///path/to/note.html', 'ftp://...', 'ws://...', or a URL whose scheme is uppercase/malformed such that parsed.protocol is not exactly 'https:' or 'http:'.

Common situations: Users converting local saved HTML pages into inputs; template interpolation producing javascript:/data: URLs; config containing internal schemes; security-filtered inputs that rewrote the scheme.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/38f2e1c855546625. Report an issue: GitHub.