jackwener/OpenCLI · error · CommandExecutionError
Malformed toutiao recommend row: invalid source_url ${JSON.s
Error message
Malformed toutiao recommend row: invalid source_url ${JSON.stringify(raw)}. What it means
firstPartyToutiaoUrl catches failures from the URL constructor itself (invalid URL syntax) and rethrows them as this CommandExecutionError. It means the row's source_url could not be parsed as a URL at all — distinct from 3824, where the URL parses but is off-domain.
Source
Thrown at clis/toutiao/utils.js:214
// The feed serves protocol-relative image URLs (`//p3.pstatp.com/...`);
// hot-board already returns absolute ones, so normalise for parity.
return raw.startsWith('//') ? `https:${raw}` : raw;
}
function firstPartyToutiaoUrl(sourceUrl) {
const raw = trimOrNull(sourceUrl);
if (!raw) return null;
try {
const url = raw.startsWith('/')
? new URL(raw, 'https://www.toutiao.com')
: new URL(raw);
if (!/^https?:$/i.test(url.protocol) || !/(^|\.)toutiao\.com$/i.test(url.hostname)) {
throw new CommandExecutionError(`Malformed toutiao recommend row: off-domain source_url ${JSON.stringify(raw)}.`);
}
return url;
} catch (error) {
if (error instanceof CommandExecutionError) throw error;
throw new CommandExecutionError(`Malformed toutiao recommend row: invalid source_url ${JSON.stringify(raw)}.`);
}
}
function articleIdFromToutiaoPath(pathname) {
return String(pathname || '').match(/^\/(?:group|article)\/([A-Za-z0-9_-]+)\/?$/)?.[1] || '';
}
function buildGroupIdentity(sourceUrl, rawGroupId) {
const source = firstPartyToutiaoUrl(sourceUrl);
const sourceId = source ? articleIdFromToutiaoPath(source.pathname) : '';
const explicitId = trimOrNull(rawGroupId);
const groupId = explicitId || trimOrNull(sourceId);
if (!groupId) {
throw new CommandExecutionError('Malformed toutiao recommend row: missing group_id and article source_url.');
}
if (!/^[A-Za-z0-9_-]+$/.test(groupId)) {
throw new CommandExecutionError(`Malformed toutiao recommend row: invalid group_id ${JSON.stringify(rawGroupId)}.`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw row and fix or drop it; the URL is unparseable so it cannot be salvaged as-is.
- Trim whitespace and decode HTML entities (&) before passing the value.
- Validate with a try { new URL(v) } catch wrapper before calling the command.
- If the value starts with a path, pass it with the leading '/' so the toutiao.com base is applied.
Example fix
// before
firstPartyToutiaoUrl(' https://www.toutiao.com/article/123/ ');
// after
firstPartyToutiaoUrl(raw.trim().replace(/&/g, '&')); Defensive patterns
Strategy: type-guard
Validate before calling
function isParsableUrl(u) { try { new URL(u, 'https://www.toutiao.com'); return true; } catch { return false; } }
if (!isParsableUrl(raw)) skipRow(raw); Type guard
const isParseableUrl = (v) => { try { new URL(String(v), 'https://www.toutiao.com'); return true; } catch { return false; } }; Try / catch
try {
const url = firstPartyToutiaoUrl(row.source_url);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('invalid source_url')) return dropRow(row);
throw e;
} Prevention
- Trim and HTML-unescape (& -> &) source_url values before use.
- Pre-validate with new URL() in a try/catch before calling the command.
- Reject empty/whitespace-only values early.
When it happens
Trigger: A source_url like 'not a url', 'http://', or containing raw spaces/characters that make new URL() throw, when the value does not start with '/' (relative '/group/...' values get a base URL and usually parse).
Common situations: Upstream feed returning empty/truncated HTML in the source_url field; escaped or double-encoded URLs; fields shifted during CSV/JSON extraction so an unrelated string lands in source_url.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed toutiao recommend row: off-domain source_url ${JSO
- Malformed toutiao recommend row: missing group_id and articl
- Malformed toutiao recommend row: invalid group_id ${JSON.str
- Malformed toutiao recommend row: group_id/source_url mismatc
- Invalid ${label}: ${raw}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/cb95752f896de41c.
Report an issue: GitHub.