different-ai/openwork · error

Invalid IANA timezone: ${timezone}

Error message

Invalid IANA timezone: ${timezone}

What it means

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.

Source

Thrown at packages/automations/src/schedule.ts:116

  }
  return shifted === null ? null : { timestamp: shifted, shifted: true }
}

function isScheduledDay(
  schedule: AutomationSchedule,
  weekday: number,
): boolean {
  return (
    schedule.kind === "daily" ||
    (schedule.kind === "weekly" && schedule.daysOfWeek.includes(weekday))
  )
}

export function assertAutomationTimezone(timezone: string): void {
  try {
    formatter(timezone).format(new Date(0))
  } catch {
    throw new RangeError(`Invalid IANA timezone: ${timezone}`)
  }
}

export interface AutomationOccurrenceSearchOptions {
  after: number
  count?: number
}

export function automationOccurrences(
  input: AutomationSchedule,
  options: AutomationOccurrenceSearchOptions,
): { occurrences: number[]; warnings: string[] } {
  const schedule = automationScheduleSchema.parse(input)
  assertAutomationTimezone(schedule.timezone)
  const count = Math.max(0, Math.min(options.count ?? 5, 5))
  if (count === 0) {
    return { occurrences: [], warnings: [] }
  }

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Use canonical IANA zone identifiers (e.g. 'America/New_York'), not offsets or abbreviations
  2. Validate user input against Intl.supportedValuesOf('timeZone') before persisting
  3. Fix the runtime environment: upgrade Node/build with full-icu so all IANA zones resolve
  4. Fall back to 'UTC' (or ask the user to re-pick) when the configured zone is invalid

Example fix

// before
assertAutomationTimezone(config.tz) // "UTC+2"
// after
const tz = Intl.supportedValuesOf("timeZone").includes(config.tz) ? config.tz : "UTC"
assertAutomationTimezone(tz)
Defensive patterns

Strategy: validation

Validate before calling

function isValidTimezone(tz: string): boolean {
  try {
    new Intl.DateTimeFormat("en-US", { timeZone: tz }).format(new Date(0))
    return true
  } catch {
    return false
  }
}
// call before: if (!isValidTimezone(config.tz)) config.tz = "UTC"

Type guard

const isIanaTimezone = (tz: string): boolean => {
  try { new Intl.DateTimeFormat("en-US", { timeZone: tz }).format(0); return true } catch { return false }
}

Try / catch

try {
  assertAutomationTimezone(tz)
} catch (e) {
  if (e instanceof RangeError && e.message.startsWith("Invalid IANA timezone")) {
    logger.warn(`${e.message}; falling back to UTC`)
    tz = "UTC"
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/1463a08e52a7a03c. Report an issue: GitHub.