{"record":{"id":"02b255e96e6c6468","repo":"koala73/worldmonitor","slug":"label-is-required","errorCode":null,"errorMessage":"${label} is required.","messagePattern":"(.+?) is required\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils/operational-balance.ts","lineNumber":15,"sourceCode":"import type { OperationalBalance, OperationalDelivery, OperationalInput, OperationalSnapshot } from '@/types/operational-balance';\n\nexport const MAX_OPERATIONAL_DAYS = 90;\nexport const MAX_OPERATIONAL_DELIVERIES = 30;\nexport const MAX_OPERATIONAL_JSON_BYTES = 65_536;\nconst DAY_MS = 86_400_000;\nconst round = (value: number) => Math.round(value * 1e6) / 1e6;\nconst dateAt = (start: string, offset: number) => new Date(Date.parse(start) + offset * DAY_MS).toISOString().slice(0, 10);\n\nfunction record(value: unknown): Record<string, unknown> {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Expected a worksheet object.');\n  return value as Record<string, unknown>;\n}\nfunction quantity(value: unknown, label: string): number {\n  if (value === '' || value === null || value === undefined) throw new Error(`${label} is required.`);\n  if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1e6 || round(value) !== value) {\n    throw new Error(`${label} must be between 0 and 1 million with at most 6 decimal places.`);\n  }\n  return value;\n}\nfunction date(value: unknown): string {\n  if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}$/.test(value) || !Number.isFinite(Date.parse(value)) || new Date(value).toISOString().slice(0, 10) !== value || value < '1900-01-01' || value > '9998-12-31') {\n    throw new Error('Use a valid date from 1900 through 9998.');\n  }\n  return value;\n}\n\nexport function parseOperationalInput(value: unknown): OperationalInput {\n  const input = record(value);\n  if (typeof input.operation !== 'string' || !input.operation.trim() || input.operation.length > 100) throw new Error('Enter an operation name of 1-100 characters.');\n  if (typeof input.unit !== 'string' || !/^[\\p{L}\\p{N} %./-]{1,24}$/u.test(input.unit) || !input.unit.trim()) throw new Error('Enter one quantity unit of 1-24 characters.');\n  const unit = input.unit.trim();\n  const startDate = date(input.startDate);","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/src/utils/operational-balance.ts#L1-L33","documentation":"The quantity() helper in operational-balance.ts throws \"${label} is required.\" when a numeric worksheet field is '', null, or undefined. Required quantity fields must be present before range/precision checks run.","triggerScenarios":"Omitting a required quantity field from the worksheet object, or explicitly sending null/'' — e.g. parseOperationalInput({ ..., initialStock: null }) or a form leaving a quantity input empty.","commonSituations":"HTML forms submitting empty strings for untouched number inputs; partial API updates dropping required fields; spreadsheet imports with blank cells mapped straight into the worksheet object.","solutions":["Supply a finite non-negative number for every required quantity field before parsing.","Coerce empty form inputs at the boundary: convert '' to undefined only after deciding a default, or reject the form client-side.","Add per-field required checks in the UI before submitting the worksheet."],"exampleFix":"// before\nparseOperationalInput({ operation: 'op', unit: 'kg', initialStock: '' });\n// after\nparseOperationalInput({ operation: 'op', unit: 'kg', initialStock: 0 });","handlingStrategy":"validation","validationCode":"const REQUIRED_QTYS = ['initialStock']; // plus any other required quantity fields\nfor (const f of REQUIRED_QTYS) {\n  const v = (payload as any)?.[f];\n  if (v === '' || v === null || v === undefined) throw new Error(`${f} is required`);\n}","typeGuard":"const hasQuantity = (w: Record<string, unknown>, f: string): w is Record<string, unknown> & Record<typeof f, number> =>\n  w[f] !== undefined && w[f] !== null && w[f] !== '';","tryCatchPattern":"try {\n  const input = parseOperationalInput(raw);\n} catch (e) {\n  if (e instanceof Error && e.message.endsWith('is required.')) {\n    console.error('Missing required quantity field:', e.message);\n  } else throw e;\n}","preventionTips":["Mark quantity inputs as required in the form UI.","Convert empty-string form values to explicit defaults or reject client-side.","For spreadsheet imports, map blank cells to a validation error, not null.","List all required quantity fields in API docs and validate at the boundary."],"tags":["validation","missing-field","required"],"backgroundTag":"empty-required-field","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}