{"record":{"id":"cc5eb4772e7d331d","repo":"sickn33/agentic-awesome-skills","slug":"data-must-be-an-object","errorCode":null,"errorMessage":"Data must be an object","messagePattern":"Data must be an object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"skills/fp-refactor/SKILL.md","lineNumber":69,"sourceCode":"- Composing multiple fallible operations is verbose\n\n### Pattern: Synchronous try-catch to Either\n\n#### Before (Imperative)\n\n```typescript\nfunction parseJSON(input: string): unknown {\n  try {\n    return JSON.parse(input);\n  } catch (error) {\n    throw new Error(`Invalid JSON: ${error}`);\n  }\n}\n\nfunction validateUser(data: unknown): User {\n  try {\n    if (!data || typeof data !== 'object') {\n      throw new Error('Data must be an object');\n    }\n    const obj = data as Record<string, unknown>;\n    if (typeof obj.name !== 'string') {\n      throw new Error('Name is required');\n    }\n    if (typeof obj.age !== 'number') {\n      throw new Error('Age must be a number');\n    }\n    return { name: obj.name, age: obj.age };\n  } catch (error) {\n    throw error;\n  }\n}\n\n// Usage with nested try-catch\nfunction processUserInput(input: string): User | null {\n  try {\n    const data = parseJSON(input);","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-refactor/SKILL.md#L51-L87","documentation":"Thrown by the throw-based validateUser in fp-refactor when the input is falsy or not an object — the outermost structural guard before field checks. It exists to reject null, undefined, primitives, and array misuse in the 'Before' code the skill refactors away.","triggerScenarios":"Calling validateUser(null), validateUser('name=Bob'), validateUser(42), or validateUser(undefined) from an unvalidated request body.","commonSituations":"Optional request bodies not checked before validation; query-string parsers returning strings; JSON.parse of 'null' producing null; form-encoded endpoints feeding primitives.","solutions":["Validate the shape at the boundary with a schema library so non-objects never reach this function","Return Either/Result with the reason instead of throwing","Add a reusable isRecord(x) type guard shared across validators"],"exampleFix":"// before\nif (!data || typeof data !== 'object') throw new Error('Data must be an object')\n\n// after\nconst isRecord = (x: unknown): x is Record<string, unknown> =>\n  typeof x === 'object' && x !== null\nconst validateUser = (data: unknown): E.Either<string, User> =>\n  !isRecord(data) ? E.left('Data must be an object') : E.right(data as User)","handlingStrategy":"type-guard","validationCode":"const isRecord = (x: unknown) => typeof x === 'object' && x !== null && !Array.isArray(x)","typeGuard":"const isRecord = (x: unknown): x is Record<string, unknown> =>\n  typeof x === 'object' && x !== null","tryCatchPattern":null,"preventionTips":["Reject non-object bodies with 400 before business validation","Share one isRecord guard across validators"],"tags":["validation","runtime-type-check","typescript"],"backgroundTag":"schema-validation-failed","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}