{"record":{"id":"662078a0102cb135","repo":"jackwener/OpenCLI","slug":"linkedin-people-search-returned-malformed-row-at-i","errorCode":null,"errorMessage":"LinkedIn people search returned malformed row at index ${index}","messagePattern":"LinkedIn people search returned malformed row at index (.+?)","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/people-search.js","lineNumber":55,"sourceCode":"        const parsed = new URL(raw);\n        const host = parsed.hostname.toLowerCase();\n        if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.port) return '';\n        if (host !== 'linkedin.com' && host !== 'www.linkedin.com') return '';\n        const match = parsed.pathname.match(/^\\/in\\/([^/?#]+)\\/?$/);\n        if (!match || !match[1]) return '';\n        return `https://www.linkedin.com/in/${match[1]}/`;\n    } catch {\n        return '';\n    }\n}\n\nfunction normalizePeopleRows(rows) {\n    if (!Array.isArray(rows)) {\n        throw new CommandExecutionError('LinkedIn people search returned malformed extraction payload: missing rows array');\n    }\n    return rows.map((row, index) => {\n        if (!row || typeof row !== 'object') {\n            throw new CommandExecutionError(`LinkedIn people search returned malformed row at index ${index}`);\n        }\n        const name = normalizeWhitespace(row.name);\n        const profileUrl = normalizeProfileUrl(row.profile_url);\n        if (!name || !profileUrl) {\n            throw new CommandExecutionError(`LinkedIn people search returned row without stable profile identity at index ${index}`);\n        }\n        return {\n            name,\n            headline: normalizeWhitespace(row.headline),\n            location: normalizeWhitespace(row.location),\n            profile_url: profileUrl,\n        };\n    });\n}\n\nfunction parseNonNegativeCount(value, label) {\n    const count = Number(value);\n    if (!Number.isInteger(count) || count < 0) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/people-search.js#L37-L73","documentation":"CommandExecutionError thrown inside normalizePeopleRows' map when an individual row is null or not an object. The rows array itself was valid, but at least one element is unusable, so the whole normalization aborts with the offending index in the message.","triggerScenarios":"The extraction script pushing null/undefined/primitive entries into the rows array — e.g. querySelectorAll matched container nodes whose expected child selectors returned nothing, or ad/promoted cards yielding null records.","commonSituations":"LinkedIn inserting promoted/ad cards with different markup; partial rendering when wait was too short; extraction script's per-row selector changes producing null entries mid-list.","solutions":["Update the extraction script to skip non-object entries instead of pushing them","Increase wait time so rows finish rendering before extraction","Filter invalid rows before normalizing: rows.filter(r => r && typeof r === 'object')","Reproduce with the failing index and inspect that row's DOM to fix the per-row selector"],"exampleFix":"// before\nreturn rows.map((row, index) => {\n  if (!row || typeof row !== 'object') {\n    throw new CommandExecutionError(`LinkedIn people search returned malformed row at index ${index}`);\n  }\n  ...\n});\n// after\nreturn rows.filter((row) => row && typeof row === 'object').map((row) => { ... });","handlingStrategy":"validation","validationCode":"const cleaned = rawRows.filter((r) => r && typeof r === 'object' && !Array.isArray(r));\nif (cleaned.length < rawRows.length) console.warn(`dropped ${rawRows.length - cleaned.length} malformed rows`);","typeGuard":"function isUsableRow(r) {\n  return typeof r === 'object' && r !== null && !Array.isArray(r);\n}","tryCatchPattern":"try {\n  return normalizePeopleRows(rows);\n} catch (err) {\n  const m = String(err.message).match(/malformed row at index (\\d+)/);\n  if (m) {\n    rows.splice(Number(m[1]), 1);\n    return normalizePeopleRows(rows);\n  }\n  throw err;\n}","preventionTips":["Filter non-object entries out of the extraction script's output before normalizing","Skip ad/promoted cards with different markup during extraction","Wait for full rendering so partially-built rows aren't captured","When a batch aborts, inspect the reported index's DOM to fix the row selector"],"tags":["linkedin","schema-validation","scraping"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}