{"record":{"id":"3369b96e9c1c73e0","repo":"sickn33/agentic-awesome-skills","slug":"email-required","errorCode":null,"errorMessage":"Email required","messagePattern":"Email required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/fp-pragmatic/SKILL.md","lineNumber":467,"sourceCode":"\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 }) =>\n      typeof obj.email === 'string' && obj.email.includes('@')\n        ? E.right(obj.email)","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/fp-pragmatic/SKILL.md#L449-L485","documentation":"Second guard in the fp-pragmatic validateUser example (skills/fp-pragmatic/SKILL.md:467). Thrown when the input passed the object check but has no string-valued email field (missing, or wrong type such as a number or null).","triggerScenarios":"validateUser with an object that has age but no email; email set to null; email set to 123: any value where typeof obj.email is not string fails.","commonSituations":"Optional-field clients omitting email; forms sending empty strings (these pass the type check but fail the later @ check); API version drift where email was renamed to emailAddress; CSV imports producing numbers for digit-only emails.","solutions":["Declare email as required in a request schema so missing or wrong-type requests get a 400 before domain code runs","Use the doc error-accumulating Either version so users see all missing fields at once","Confirm field naming consistency between client and server (email vs emailAddress)"],"exampleFix":"// before\nif (typeof obj.email !== 'string') throw new Error('Email required')\n\n// after\nconst errors: string[] = []\nif (typeof obj.email !== 'string') errors.push('Email required')\n// ... collect remaining checks, then return E.left(errors) or E.right(user)","handlingStrategy":"type-guard","validationCode":"const isRecord = (u: unknown): u is Record<string, unknown> =>\n  typeof u === 'object' && u !== null\nif (!isRecord(data) || typeof data.email !== 'string') {\n  return badRequest('email is required and must be a string')\n}","typeGuard":"const hasEmailString = (u: Record<string, unknown>): u is { email: string } =>\n  typeof u.email === 'string'","tryCatchPattern":null,"preventionTips":["Declare required fields in a request schema (400 before domain logic)","Keep client/server field naming in sync","Accumulate all missing-field errors in one response"],"tags":["validation","missing-field","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}