cube-js/cube · error · Error
Unknown timezone: ${timezone}
Error message
Unknown timezone: ${timezone} What it means
localTimestampToUtc in packages/cubejs-backend-shared/src/time.ts converts a 23- or 26-character local timestamp to UTC using the IANA timezone's offset via moment.tz.zone(timezone). If the timezone name is not a valid IANA zone (moment returns no zone object), it throws 'Unknown timezone'. This prevents silently applying UTC offsets of 0 for unrecognized zones.
Source
Thrown at packages/cubejs-backend-shared/src/time.ts:277
export const FROM_PARTITION_RANGE = '__FROM_PARTITION_RANGE';
export const TO_PARTITION_RANGE = '__TO_PARTITION_RANGE';
export const BUILD_RANGE_START_LOCAL = '__BUILD_RANGE_START_LOCAL';
export const BUILD_RANGE_END_LOCAL = '__BUILD_RANGE_END_LOCAL';
/**
* Takes timestamp, treat it as time in provided timezone and returns the corresponding timestamp in UTC
*/
export const localTimestampToUtc = (timezone: string, timestampFormat: string, timestamp?: string): string | null => {
if (!timestamp) {
return null;
}
if (timestamp.length === 23 || timestamp.length === 26) {
const zone = moment.tz.zone(timezone);
if (!zone) {
throw new Error(`Unknown timezone: ${timezone}`);
}
const parsedTime = Date.parse(`${timestamp}Z`);
const offset = zone.utcOffset(parsedTime);
const inDbTimeZoneDate = new Date(parsedTime + offset * 60 * 1000);
if (timestampFormat === 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' || timestampFormat === 'YYYY-MM-DDTHH:mm:ss.SSSZ') {
return inDbTimeZoneDate.toJSON();
} else if (timestampFormat === 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]' || timestampFormat === 'YYYY-MM-DDTHH:mm:ss.SSSSSSZ') {
const value = inDbTimeZoneDate.toJSON();
if (value.endsWith('999Z')) {
// emulate microseconds
return value.replace('Z', '999Z');
}
// emulate microseconds
return value.replace('Z', '000Z');
} else if (timestampFormat === 'YYYY-MM-DDTHH:mm:ss.SSS') {View on GitHub (pinned to 7d981676b3)
Solutions
- Pass a valid IANA timezone name, e.g. 'America/New_York', 'Europe/Berlin', 'UTC'.
- Validate with moment.tz.zone(tz) (or Intl.supportedValuesOf('timeZone')) before calling.
- Convert Windows/CLDR zone names to IANA (e.g. via a CLDR-to-IANA mapping library) before use.
- Check casing/whitespace: normalize (trim, exact case) the configured timezone.
Example fix
// before localTimestampToUtc(ts, 'Eastern Standard Time'); // throws // after localTimestampToUtc(ts, 'America/New_York');
Defensive patterns
Strategy: validation
Validate before calling
import moment from 'moment-timezone';
function assertTimezone(tz: string) {
if (!moment.tz.zone(tz)) {
throw new Error(`'${tz}' is not a valid IANA timezone; see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones`);
}
} Type guard
function isIanaTimezone(tz: unknown): tz is string {
return typeof tz === 'string' && tz.length > 0 && moment.tz.zone(tz) !== null;
} Try / catch
try {
return localTimestampToUtc(ts, tz);
} catch (e) {
if (/Unknown timezone/.test(String(e))) {
console.warn(`Unknown timezone '${tz}', falling back to UTC`);
return localTimestampToUtc(ts, 'UTC');
}
throw e;
} Prevention
- Store only IANA names ('America/New_York'), never fixed offsets or Windows names
- Validate timezone at config-load and at API boundaries
- Map CLDR/Windows zone names to IANA before use
- Add Intl.supportedValuesOf('timeZone') check in browsers
When it happens
Trigger: localTimestampToUtc('2024-01-01T00:00:00.000', 'America/NewYork') or any call where timezone is misspelled, a fixed-offset string like 'UTC+2', an empty string, or a Windows zone name like 'Eastern Standard Time' — with a timestamp of length 23 or 26.
Common situations: Timezone read from user config/browser with wrong casing or typos; Windows (CLDR) timezone names instead of IANA names; environment defaults like 'local' or 'system' passed through.
Related errors
- Value "${raw}" is not valid for CUBEJS_SCHEDULED_REFRESH_TIM
- Value "${value}" is not valid for CUBEJS_DEFAULT_TIMEZONE. M
- The count of generated date ranges (${count}) for the reques
- Timezone must be a string, got ${typeof value}
- Timezone must not be empty
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/e5d46594eba86112.
Report an issue: GitHub.