{"record":{"id":"4eb3a9db73945a79","repo":"sickn33/agentic-awesome-skills","slug":"must-be-object","errorCode":null,"errorMessage":"Must be object","messagePattern":"Must be object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-pragmatic/SKILL.md","lineNumber":465,"sourceCode":"    O.flatMap(m => O.fromNullable(m.email))\n  )\n\n// Use it\npipe(\n  getManagerEmail(employee),\n  O.fold(\n    () => sendToDefault(),\n    (email) => sendTo(email)\n  )\n)\n```\n\n### Validation with Multiple Checks\n\n```typescript\n// Before: Throws on first error\nfunction validateUser(data: unknown): User {\n  if (!data || typeof data !== 'object') throw new Error('Must be object')\n  const obj = data as Record<string, unknown>\n  if (typeof obj.email !== 'string') throw new Error('Email required')\n  if (!obj.email.includes('@')) throw new Error('Invalid email')\n  if (typeof obj.age !== 'number') throw new Error('Age required')\n  if (obj.age < 0) throw new Error('Age must be positive')\n  return obj as User\n}\n\n// After: Returns first error, type-safe\nconst validateUser = (data: unknown): E.Either<string, User> =>\n  pipe(\n    E.Do,\n    E.bind('obj', () =>\n      typeof data === 'object' && data !== null\n        ? E.right(data as Record<string, unknown>)\n        : E.left('Must be object')\n    ),\n    E.bind('email', ({ obj }) =>","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-pragmatic/SKILL.md#L447-L483","documentation":"First guard of the multi-check validateUser example in the fp-pragmatic skill (skills/fp-pragmatic/SKILL.md:465). Thrown when the raw input is falsy or not an object: the shape check that must pass before any field can be safely read. The doc replaces this throw-on-first-error style with an error-accumulating Either version.","triggerScenarios":"Calling validateUser with null, undefined, a string, a number, or an array: anything where typeof data is not object or data is null.","commonSituations":"JSON.parse of an empty or malformed request body producing null; query-string params arriving as strings; arrays passing the typeof check but failing later field checks; API consumers sending scalars where objects are expected.","solutions":["Parse and validate the payload shape at the boundary with a schema library (zod, io-ts, valibot) before it reaches domain code","Use the doc AFTER pattern: return Either with accumulated errors instead of throwing on the first failed check","Reject non-object bodies early in the HTTP layer with a 400 and a clear message"],"exampleFix":"// before\nif (!data || typeof data !== 'object') throw new Error('Must be object')\n\n// after\nconst isRecord = (u: unknown): u is Record<string, unknown> =>\n  typeof u === 'object' && u !== null && !Array.isArray(u)\nif (!isRecord(data)) return E.left(['Must be object'])","handlingStrategy":"type-guard","validationCode":"if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n  return badRequest('body must be a JSON object')\n}","typeGuard":"const isRecord = (u: unknown): u is Record<string, unknown> =>\n  typeof u === 'object' && u !== null && !Array.isArray(u)","tryCatchPattern":null,"preventionTips":["Validate payload shape at the HTTP boundary before domain code","Use zod/io-ts schemas for unknown input","Accumulate validation errors instead of throwing on the first"],"tags":["validation","type-checking","unknown-input"],"backgroundTag":"schema-validation-failed","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}