{"record":{"id":"1463a08e52a7a03c","repo":"different-ai/openwork","slug":"invalid-iana-timezone-timezone","errorCode":null,"errorMessage":"Invalid IANA timezone: ${timezone}","messagePattern":"Invalid IANA timezone: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/automations/src/schedule.ts","lineNumber":116,"sourceCode":"  }\n  return shifted === null ? null : { timestamp: shifted, shifted: true }\n}\n\nfunction isScheduledDay(\n  schedule: AutomationSchedule,\n  weekday: number,\n): boolean {\n  return (\n    schedule.kind === \"daily\" ||\n    (schedule.kind === \"weekly\" && schedule.daysOfWeek.includes(weekday))\n  )\n}\n\nexport function assertAutomationTimezone(timezone: string): void {\n  try {\n    formatter(timezone).format(new Date(0))\n  } catch {\n    throw new RangeError(`Invalid IANA timezone: ${timezone}`)\n  }\n}\n\nexport interface AutomationOccurrenceSearchOptions {\n  after: number\n  count?: number\n}\n\nexport function automationOccurrences(\n  input: AutomationSchedule,\n  options: AutomationOccurrenceSearchOptions,\n): { occurrences: number[]; warnings: string[] } {\n  const schedule = automationScheduleSchema.parse(input)\n  assertAutomationTimezone(schedule.timezone)\n  const count = Math.max(0, Math.min(options.count ?? 5, 5))\n  if (count === 0) {\n    return { occurrences: [], warnings: [] }\n  }","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/automations/src/schedule.ts#L98-L134","documentation":"assertAutomationTimezone validates that a string is an IANA timezone the platform can format with (via Intl.DateTimeFormat). It constructs a formatter and formats epoch 0; any failure (unknown zone, bad identifier) raises a RangeError naming the offending timezone. Automation schedules need a real zone to compute occurrences.","triggerScenarios":"Calling assertAutomationTimezone (directly or via automationOccurrences) with a string that is not a valid IANA zone — misspelled names, 'UTC+2'-style offsets, empty strings, legacy aliases unsupported by the runtime, or user-supplied config values.","commonSituations":"Storing user-entered timezone strings from a settings UI; using fixed offset strings like 'GMT+1' instead of 'Europe/Paris'; environments (old Node, minimal ICU) lacking full tzdata so valid zones fail; locale-dependent aliases.","solutions":["Use canonical IANA zone identifiers (e.g. 'America/New_York'), not offsets or abbreviations","Validate user input against Intl.supportedValuesOf('timeZone') before persisting","Fix the runtime environment: upgrade Node/build with full-icu so all IANA zones resolve","Fall back to 'UTC' (or ask the user to re-pick) when the configured zone is invalid"],"exampleFix":"// before\nassertAutomationTimezone(config.tz) // \"UTC+2\"\n// after\nconst tz = Intl.supportedValuesOf(\"timeZone\").includes(config.tz) ? config.tz : \"UTC\"\nassertAutomationTimezone(tz)","handlingStrategy":"validation","validationCode":"function isValidTimezone(tz: string): boolean {\n  try {\n    new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }).format(new Date(0))\n    return true\n  } catch {\n    return false\n  }\n}\n// call before: if (!isValidTimezone(config.tz)) config.tz = \"UTC\"","typeGuard":"const isIanaTimezone = (tz: string): boolean => {\n  try { new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }).format(0); return true } catch { return false }\n}","tryCatchPattern":"try {\n  assertAutomationTimezone(tz)\n} catch (e) {\n  if (e instanceof RangeError && e.message.startsWith(\"Invalid IANA timezone\")) {\n    logger.warn(`${e.message}; falling back to UTC`)\n    tz = \"UTC\"\n  } else throw e\n}","preventionTips":["Constrain timezone selection to a dropdown sourced from Intl.supportedValuesOf('timeZone')","Store canonical IANA identifiers ('Europe/Paris'), never offsets like 'UTC+2'","Run Node with full ICU data in minimal/container environments","Validate timezone config at load time, not at schedule computation time"],"tags":["timezone","validation","configuration"],"backgroundTag":"invalid-iana-timezone","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}