jackwener/OpenCLI · error · CommandExecutionError
${context} returned malformed row ${index + 1}.
Error message
${context} returned malformed row ${index + 1}. What it means
requireNonEmptyRowField validates each scraped row before the CLI returns it. If a row is not a plain object (null, array, primitive) it throws CommandExecutionError '<context> returned malformed row N.' This means the in-page scrape produced an element that violates the row contract, indicating a DOM/scrape mismatch rather than legitimately missing data.
Source
Thrown at clis/discord-app/utils.js:36
function requireObjectEvaluateResult(payload, context) {
const value = unwrapEvaluateResult(payload);
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new CommandExecutionError(`${context} returned malformed browser output.`);
}
return value;
}
function requireArrayEvaluateResult(payload, context) {
const value = unwrapEvaluateResult(payload);
if (!Array.isArray(value)) {
throw new CommandExecutionError(`${context} returned malformed browser output.`);
}
return value;
}
function requireNonEmptyRowField(row, field, context, index) {
if (!row || typeof row !== 'object' || Array.isArray(row)) {
throw new CommandExecutionError(`${context} returned malformed row ${index + 1}.`);
}
const value = String(row[field] || '').trim();
if (!value) {
throw new CommandExecutionError(`${context} row ${index + 1} is missing ${field}.`);
}
return value;
}
function requireRowsWithFields(rows, fields, context) {
rows.forEach((row, index) => {
fields.forEach((field) => requireNonEmptyRowField(row, field, context, index));
});
return rows;
}
export function isDiscordSnowflake(value) {
return CHANNEL_ID_RE.test(String(value || '').trim());
}View on GitHub (pinned to 49907e53dc)
Solutions
- Filter non-object entries from the scrape script's returned array in clis/discord-app/utils.js before validation
- Re-run after the page fully loads so placeholder/skeleton nodes are gone
- Check whether a recent Discord UI update broke the row-mapping logic in the relevant build*Script
- Pin/work around by scraping fewer rows (lower --count/--limit) if only late-loading rows are malformed
Example fix
// inside the page script, before returning // before return nodes.map(n => extract(n)); // after return nodes.map(n => extract(n)).filter(r => r && typeof r === 'object' && !Array.isArray(r));
Defensive patterns
Strategy: validation
Validate before calling
function validateRows(rows) {
rows.forEach((r, i) => {
if (!r || typeof r !== 'object' || Array.isArray(r)) {
throw new Error(`Row ${i + 1} is not an object — filter non-object entries before returning rows.`);
}
});
} Type guard
function isRow(r) {
return r !== null && typeof r === 'object' && !Array.isArray(r);
} Try / catch
try {
const rows = await discordAppChannels(page);
} catch (err) {
if (/malformed row \d+/.test(String(err.message))) {
console.error('Scrape produced a non-object row: re-run after full load or fix the row-mapping script.');
} else throw err;
} Prevention
- Filter null/undefined entries out of scrape results in the page script
- Wait for the list to fully render so skeleton placeholders aren't captured
- Re-check row-mapping selectors after Discord UI changes
- Keep custom scrape patches aligned with the row contract
When it happens
Trigger: listDiscordChannels/listDiscordServers/readDiscordMessages/listDiscordThreads returning rows where an entry is null or not an object — e.g. the scrape script pushes undefined for unmatched DOM nodes, or Discord renders placeholder/ghost nodes the script maps to non-objects.
Common situations: Discord UI changes causing the row-mapping script to emit undefined entries; a partially-loaded list where skeleton placeholders are captured; custom or modified scrape scripts returning mixed-shape arrays.
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
- ${context} row ${index + 1} is missing ${field}.
- discord-app channels
- discord-app read
- Discord search returned malformed browser payload.
- Discord search result selector returned no rows and no expli
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/258e57f77785e3cb.
Report an issue: GitHub.