{"record":{"id":"1e6d0b631a08286f","repo":"jackwener/OpenCLI","slug":"nowcoder-returned-malformed-label-authorship","errorCode":null,"errorMessage":"Nowcoder returned malformed ${label} authorship","messagePattern":"Nowcoder returned malformed (.+?) authorship","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":99,"sourceCode":"    for (const block of preBlocks) text = text.replace(block.token, block.text);\n    return text;\n}\n\nfunction isoTime(value, label) {\n    if (!Number.isSafeInteger(value) || value <= 0) throw new CommandExecutionError(`Nowcoder returned a malformed ${label}`);\n    const date = new Date(value);\n    if (Number.isNaN(date.getTime())) throw new CommandExecutionError(`Nowcoder returned a malformed ${label}`);\n    return date.toISOString();\n}\n\nfunction metric(frequency, key) {\n    const value = frequency[key];\n    if (!Number.isSafeInteger(value) || value < 0) throw new CommandExecutionError(`Nowcoder returned a malformed frequencyData.${key}`);\n    return value;\n}\n\nfunction authorFields(userBrief, expectedId, label) {\n    if (!isRecord(userBrief)) throw new CommandExecutionError(`Nowcoder returned malformed ${label} authorship`);\n    const authorId = requiredId(userBrief.userId, `${label} userBrief.userId`);\n    if (authorId !== requiredId(expectedId, `${label} author id`)) throw new CommandExecutionError(`Nowcoder returned mismatched ${label} authorship`);\n    return {\n        author: optionalText(userBrief.nickname, `${label} author nickname`),\n        author_id: authorId,\n        author_url: `https://www.nowcoder.com/users/${authorId}`,\n        school: optionalText(userBrief.educationInfo, `${label} author education`),\n    };\n}\n\nfunction commonFeedFields(data, post, postType, authorId, timestamp, index) {\n    if (!isRecord(data.frequencyData)) throw new CommandExecutionError(`Nowcoder returned malformed ${postType} frequencyData`);\n    return {\n        rank: index + 1,\n        post_type: postType,\n        title: optionalText(post.title, `${postType} title`) || '(untitled)',\n        ...authorFields(data.userBrief, authorId, postType),\n        content: cleanBody(post.content, `${postType} content`),","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L81-L117","documentation":"authorFields() expects data.userBrief to be a plain object containing the post author's profile summary. This throw fires when userBrief is missing, null, an array, or another non-object — the library cannot build author fields (author, author_id, author_url, school) and refuses to emit fabricated authorship data.","triggerScenarios":"A feed row (commonFeedFields → authorFields) or detail payload (projectNowcoderDetail) has data.userBrief absent/null because Nowcoder omitted the author block — e.g. deleted accounts, anonymous or removed posts, or degraded unauthenticated responses.","commonSituations":"Author account deleted or banned after posting; scraping without a logged-in session returns rows without userBrief; API change nests author info elsewhere (e.g. data.authorInfo); ad/promoted entries lack real author objects.","solutions":["Log the raw record and confirm whether userBrief exists for the failing item","Retry with a valid logged-in Nowcoder session — degraded payloads often omit author data","If Nowcoder moved the author block, remap the new field (e.g. data.author) to userBrief before calling, or update the library","Filter out feed records without a userBrief object before projection"],"exampleFix":"// before\nprojectFeedData(record.data, i, true)\n// after\nif (!record?.data?.userBrief) continue; // skip rows with no author block\nprojectFeedData(record.data, i, true)","handlingStrategy":"type-guard","validationCode":"function hasAuthorBrief(data) {\n  return Boolean(data?.userBrief) && typeof data.userBrief === 'object' && !Array.isArray(data.userBrief);\n}\n// pre-filter: records.filter(r => hasAuthorBrief(r.data))","typeGuard":"function isUserBrief(value) {\n  return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n    && (typeof value.userId === 'number' || typeof value.userId === 'string');\n}","tryCatchPattern":"try {\n  const rows = projectNowcoderFeed(records, limit, source);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /malformed .* authorship/.test(err.message)) {\n    // drop rows without a userBrief object or re-authenticate\n  } else throw err;\n}","preventionTips":["Pre-filter feed records lacking a userBrief object","Re-authenticate: unauthenticated sessions yield degraded payloads without author blocks","Remap renamed author fields (authorInfo → userBrief) after API changes","Expect missing author blocks for deleted/banned accounts and handle them"],"tags":["nowcoder","api-schema","author","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}