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
- Use the https form of the share URL: https://share.note.youdao.com/ynoteshare/index.html?id=<id>&type=note
- Strip or replace non-http(s) schemes in your input pipeline before calling the command
- 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
- Only feed http(s) URLs into browser-automation commands
- Reject file:// or javascript: schemes in input sanitation
- Normalize schemes to https for Youdao share links
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
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/38f2e1c855546625.
Report an issue: GitHub.