{"record":{"id":"58ddc9462a3a6eb0","repo":"affaan-m/ECC","slug":"skill-execution-payload-must-be-an-object","errorCode":null,"errorMessage":"skill execution payload must be an object","messagePattern":"skill execution payload must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/tracker.js","lineNumber":47,"sourceCode":"  return path.join(resolveHomeDir(options.homeDir), '.claude', 'state', 'skill-runs.jsonl');\n}\n\nfunction toNullableNumber(value, fieldName) {\n  if (value === null || typeof value === 'undefined') {\n    return null;\n  }\n\n  const numericValue = Number(value);\n  if (!Number.isFinite(numericValue)) {\n    throw new Error(`${fieldName} must be a number`);\n  }\n\n  return numericValue;\n}\n\nfunction normalizeExecutionRecord(input, options = {}) {\n  if (!input || typeof input !== 'object' || Array.isArray(input)) {\n    throw new Error('skill execution payload must be an object');\n  }\n\n  const skillId = input.skill_id || input.skillId;\n  const skillVersion = input.skill_version || input.skillVersion;\n  const taskDescription = input.task_description || input.task_attempted || input.taskAttempted;\n  const outcome = input.outcome;\n  const recordedAt = input.recorded_at || options.now || new Date().toISOString();\n  const userFeedback = input.user_feedback || input.userFeedback || null;\n\n  if (typeof skillId !== 'string' || skillId.trim().length === 0) {\n    throw new Error('skill_id is required');\n  }\n\n  if (typeof skillVersion !== 'string' || skillVersion.trim().length === 0) {\n    throw new Error('skill_version is required');\n  }\n\n  if (typeof taskDescription !== 'string' || taskDescription.trim().length === 0) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/skill-evolution/tracker.js#L29-L65","documentation":"normalizeExecutionRecord() validates the payload handed to record() before persisting a skill execution entry. The payload must be a plain object: null, undefined, arrays, and primitives are all rejected with 'skill execution payload must be an object'. This fails fast so downstream field extraction (skill_id, skill_version, etc.) operates on real object input.","triggerScenarios":"Calling record(null), record(undefined), record([...] ) with an array of records, or record('skill run') — any input where !input || typeof input !== 'object' || Array.isArray(input) is true.","commonSituations":"Passing an array of execution records to record() instead of looping; spreading arguments so the payload becomes undefined; a build step that dropped the object argument; JSON.parse failures silently yielding undefined then passed through.","solutions":["Pass a single execution-record object to record(), e.g. record({ skill_id, skill_version, task_description, outcome }).","If you have multiple records, call record() once per object in a loop/map instead of passing an array.","Check the call site for a missing argument or failed JSON.parse returning undefined.","Guard with a type check before calling: if (payload && !Array.isArray(payload)) record(payload)."],"exampleFix":"// before\ntracker.record(JSON.parse(batchFile)); // array of records\n\n// after\nfor (const rec of JSON.parse(batchFile)) {\n  tracker.record(rec);\n}","handlingStrategy":"type-guard","validationCode":"function isRecordPayload(input) {\n  return input !== null && typeof input === 'object' && !Array.isArray(input);\n}\n\nif (!isRecordPayload(payload)) {\n  throw new TypeError('record() expects a single execution object, not an array or primitive');\n}\ntracker.record(payload);","typeGuard":"function isPlainObject(value) {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}","tryCatchPattern":"try {\n  tracker.record(payload);\n} catch (err) {\n  if (err.message === 'skill execution payload must be an object') {\n    console.error('record() received non-object payload; check for missing arg or array batch');\n    return;\n  }\n  throw err;\n}","preventionTips":["Never pass arrays to record(); loop over batches one record at a time.","Check JSON.parse results for undefined/null before passing them on.","Wrap record() in a thin adapter that validates the payload shape first."],"tags":["skill-evolution","validation","payload-shape"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}