{"record":{"id":"ada9a4e492acde6c","repo":"koala73/worldmonitor","slug":"start-date-must-be-yyyy-mm-dd","errorCode":null,"errorMessage":"start_date must be YYYY-MM-DD","messagePattern":"start_date must be YYYY-MM-DD","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"server/worldmonitor/intelligence/v1/search-sec-filings.ts","lineNumber":49,"sourceCode":"  const startDateValid = !req.startDate || isEdgarIsoDate(req.startDate);\n  const endDateValid = !req.endDate || isEdgarIsoDate(req.endDate);\n  const violations = [\n    ...(formsNormalized === null\n      ? [{ field: 'forms', description: 'forms must be a comma-separated form list such as \"8-K\" or \"10-K,10-Q\"' }]\n      : []),\n    ...(!startDateValid\n      ? [{ field: 'start_date', description: 'start_date must be YYYY-MM-DD' }]\n      : []),\n    ...(!endDateValid\n      ? [{ field: 'end_date', description: 'end_date must be YYYY-MM-DD' }]\n      : []),\n    ...(req.startDate && req.endDate\n      && startDateValid && endDateValid\n      && req.startDate > req.endDate\n      ? [{ field: 'start_date', description: 'start_date must not be after end_date' }]\n      : []),\n  ];\n  if (violations.length > 0) throw new ValidationError(violations);\n\n  const limit = req.limit > 0 ? Math.min(req.limit, MAX_LIMIT) : DEFAULT_LIMIT;\n\n  const result = await searchEdgarFullText({\n    query,\n    forms: formsNormalized || undefined,\n    startDate: req.startDate,\n    endDate: req.endDate,\n    size: limit,\n  });\n\n  if (!result) {\n    return { results: [], total: 0, unavailable: true, fetchedAtMs: Date.now() };\n  }\n\n  return {\n    results: result.results.slice(0, limit),\n    total: result.total,","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/server/worldmonitor/intelligence/v1/search-sec-filings.ts#L31-L67","documentation":"searchSecFilings includes this violation (field 'start_date') when req.startDate is present but fails isEdgarIsoDate — EDGAR full-text search accepts strict YYYY-MM-DD calendar dates only. The fail-closed design means a malformed date is reported instead of silently dropped, because dropping it would widen the date range and return filings the caller believes were excluded. It is thrown together with any other accumulated violations.","triggerScenarios":"startDate='2024/01/01' (slashes); ISO datetime '2024-01-01T00:00:00Z'; compact '20240101'; locale-formatted '01-01-2024'; trailing whitespace or newline in the value.","commonSituations":"Date picked in a UI and serialized with the locale format; Date.toISOString() used directly (produces a full timestamp, not a date); API gateway re-encoding parameters; copy-pasted dates from spreadsheets.","solutions":["Format dates as YYYY-MM-DD before sending — e.g. date.toISOString().slice(0, 10)","Validate with a strict /^\\d{4}-\\d{2}-\\d{2}$/ check plus a real-calendar parse on the client","Leave start_date unset when you only want an end-date-bounded search"],"exampleFix":"// before — full ISO timestamp sent\n{ query: 'insider sales', startDate: fromDate.toISOString() }\n\n// after — calendar date only\n{ query: 'insider sales', startDate: fromDate.toISOString().slice(0, 10) }","handlingStrategy":"validation","validationCode":"// strict EDGAR calendar-date check (shape + real calendar day)\nfunction isEdgarIsoDate(s: string): boolean {\n  if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return false;\n  const d = new Date(`${s}T00:00:00Z`);\n  return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === s;\n}\nconst startDate = rawStart ? rawStart.toISOString().slice(0, 10) : undefined;","typeGuard":"function isStartDateViolation(body: unknown): boolean {\n  const v = (body as { violations?: { field?: string }[] })?.violations;\n  return Array.isArray(v) && v.some((x) => x.field === 'start_date');\n}","tryCatchPattern":"try {\n  await searchSecFilings({ query, startDate });\n} catch (e) {\n  if (e instanceof HttpError && e.status === 400 && isStartDateViolation(e.body)) {\n    return reformatDatePicker(); // strict YYYY-MM-DD required; timestamps and slashes rejected\n  }\n  throw e;\n}","preventionTips":["Never send Date.toISOString() verbatim — slice(0, 10) it to YYYY-MM-DD","Configure date pickers to emit ISO calendar dates, not locale formats","Validate shape and calendar validity client-side; also ensure start_date <= end_date to avoid the sibling violation"],"tags":["intelligence","sec","edgar","validation","date-format"],"backgroundTag":"invalid-date-format","analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}