{"record":{"id":"d57d581e22ff94df","repo":"jackwener/OpenCLI","slug":"nowcoder-returned-a-malformed-frequencydata-key","errorCode":null,"errorMessage":"Nowcoder returned a malformed frequencyData.${key}","messagePattern":"Nowcoder returned a malformed frequencyData\\.(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":94,"sourceCode":"        .split('\\n')\n        .map((line) => line.replace(/[\\t ]+/g, ' ').trim())\n        .join('\\n')\n        .replace(/^\\s+|\\s+$/g, '')\n        .replace(/\\n{3,}/g, '\\n\\n');\n    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 {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L76-L112","documentation":"metric() reads a counter (likeCnt, commentCnt, viewCnt) from data.frequencyData and requires a non-negative safe integer. This error means the engagement-count field named in the message is missing, null, a float, negative, or a non-numeric type in the Nowcoder payload — the library refuses to invent default counts.","triggerScenarios":"data.frequencyData.likeCnt/commentCnt/viewCnt is undefined (field renamed or dropped), a string like '12', a float, or -1 in a feed row (commonFeedFields) or detail payload (projectNowcoderDetail).","commonSituations":"Nowcoder renames counters (e.g. likeCnt → likeCount); newly created posts omit count fields entirely; API A/B tests return string counts; region-localized payloads format numbers as strings.","solutions":["Log data.frequencyData for the failing item and compare its keys to likeCnt/commentCnt/viewCnt","If fields were renamed, update the library or map the new names before calling","Coerce string counts with Number(value) in wrapper code when the payload returns stringified integers","Skip or default-count items whose frequencyData lacks the fields (only in your own pre-processing)"],"exampleFix":"// before\nconst likes = data.frequencyData.likeCnt; // now 'likeCount'\n// after\nconst likes = data.frequencyData.likeCnt ?? data.frequencyData.likeCount;","handlingStrategy":"validation","validationCode":"const REQUIRED_METRICS = ['likeCnt', 'commentCnt', 'viewCnt'];\nfunction hasValidFrequency(data) {\n  const f = data?.frequencyData;\n  return Boolean(f) && typeof f === 'object' && !Array.isArray(f)\n    && REQUIRED_METRICS.every(k => Number.isSafeInteger(f[k]) && f[k] >= 0);\n}","typeGuard":"function isFrequencyData(value) {\n  return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n    && ['likeCnt','commentCnt','viewCnt'].every(k => Number.isSafeInteger(value[k]) && value[k] >= 0);\n}","tryCatchPattern":"try {\n  const rows = projectNowcoderFeed(records, limit, source);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /frequencyData\\./.test(err.message)) {\n    const key = err.message.match(/frequencyData\\.(\\w+)/)?.[1];\n    // remap renamed metric key or skip the row\n  } else throw err;\n}","preventionTips":["Check likeCnt/commentCnt/viewCnt names after each Nowcoder API update","Coerce stringified counts with Number() when the API returns strings","Skip or default rows whose frequencyData lacks metrics (in your own preprocessing)","Compare frequencyData keys against a known-good captured payload when errors spike"],"tags":["nowcoder","api-schema","metrics","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}