{"record":{"id":"258e57f77785e3cb","repo":"jackwener/OpenCLI","slug":"context-returned-malformed-row-index-1","errorCode":null,"errorMessage":"${context} returned malformed row ${index + 1}.","messagePattern":"(.+?) returned malformed row (.+?)\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/discord-app/utils.js","lineNumber":36,"sourceCode":"function requireObjectEvaluateResult(payload, context) {\n    const value = unwrapEvaluateResult(payload);\n    if (!value || typeof value !== 'object' || Array.isArray(value)) {\n        throw new CommandExecutionError(`${context} returned malformed browser output.`);\n    }\n    return value;\n}\n\nfunction requireArrayEvaluateResult(payload, context) {\n    const value = unwrapEvaluateResult(payload);\n    if (!Array.isArray(value)) {\n        throw new CommandExecutionError(`${context} returned malformed browser output.`);\n    }\n    return value;\n}\n\nfunction requireNonEmptyRowField(row, field, context, index) {\n    if (!row || typeof row !== 'object' || Array.isArray(row)) {\n        throw new CommandExecutionError(`${context} returned malformed row ${index + 1}.`);\n    }\n    const value = String(row[field] || '').trim();\n    if (!value) {\n        throw new CommandExecutionError(`${context} row ${index + 1} is missing ${field}.`);\n    }\n    return value;\n}\n\nfunction requireRowsWithFields(rows, fields, context) {\n    rows.forEach((row, index) => {\n        fields.forEach((field) => requireNonEmptyRowField(row, field, context, index));\n    });\n    return rows;\n}\n\nexport function isDiscordSnowflake(value) {\n    return CHANNEL_ID_RE.test(String(value || '').trim());\n}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/discord-app/utils.js#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// inside the page script, before returning\n// before\nreturn nodes.map(n => extract(n));\n// after\nreturn nodes.map(n => extract(n)).filter(r => r && typeof r === 'object' && !Array.isArray(r));","handlingStrategy":"validation","validationCode":"function validateRows(rows) {\n  rows.forEach((r, i) => {\n    if (!r || typeof r !== 'object' || Array.isArray(r)) {\n      throw new Error(`Row ${i + 1} is not an object — filter non-object entries before returning rows.`);\n    }\n  });\n}","typeGuard":"function isRow(r) {\n  return r !== null && typeof r === 'object' && !Array.isArray(r);\n}","tryCatchPattern":"try {\n  const rows = await discordAppChannels(page);\n} catch (err) {\n  if (/malformed row \\d+/.test(String(err.message))) {\n    console.error('Scrape produced a non-object row: re-run after full load or fix the row-mapping script.');\n  } else throw err;\n}","preventionTips":["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"],"tags":["discord","data-validation","scraping"],"backgroundTag":"malformed-row-data","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}