{"record":{"id":"bd4c88c342f5abbf","repo":"louislam/dockge","slug":"invalid-timezone","errorCode":null,"errorMessage":"Invalid timezone:","messagePattern":"Invalid timezone:","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"backend/dockge-server.ts","lineNumber":540,"sourceCode":"    /**\n     * Get the current offset\n     * @returns {string} Time offset\n     */\n    getTimezoneOffset() {\n        return dayjs().format(\"Z\");\n    }\n\n    /**\n     * Throw an error if the timezone is invalid\n     * @param {string} timezone Timezone to test\n     * @returns {void}\n     * @throws The timezone is invalid\n     */\n    checkTimezone(timezone : string) {\n        try {\n            dayjs.utc(\"2013-11-18 11:55\").tz(timezone).format();\n        } catch (e) {\n            throw new Error(\"Invalid timezone:\" + timezone);\n        }\n    }\n\n    /**\n     * Initialize the data directory\n     */\n    initDataDir() {\n        if (! fs.existsSync(this.config.dataDir)) {\n            fs.mkdirSync(this.config.dataDir, { recursive: true });\n        }\n\n        // Check if a directory\n        if (!fs.lstatSync(this.config.dataDir).isDirectory()) {\n            throw new Error(`Fatal error: ${this.config.dataDir} is not a directory`);\n        }\n\n        // Create data/stacks directory\n        if (!fs.existsSync(this.stacksDir)) {","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/dockge-server.ts#L522-L558","documentation":"DockgeServer.checkTimezone validates a timezone string by attempting dayjs.utc(...).tz(timezone); if dayjs throws (unknown timezone for the IANA db, or the utcOffset plugin misuse), it rethrows 'Invalid timezone:<timezone>'. Timezones must be IANA names resolvable by dayjs's timezone plugin.","triggerScenarios":"Calling getTimezone/checkTimezone with e.g. 'UTC+2', 'GMT-5', 'CET', an empty string, or a misspelled IANA name like 'Europe/Berlin ' with trailing space.","commonSituations":"Client sends a browser locale string instead of an IANA zone; fixed-offset strings like UTC+8 that are not IANA names; server missing timezone data so even valid names throw; dayjs timezone plugin not properly extended in a custom build.","solutions":["Pass a valid IANA timezone name such as 'Europe/Berlin' or 'Asia/Tokyo'","For fixed offsets, map them to Etc/GMT zones, e.g. UTC+8 -> 'Etc/GMT-8' (inverted sign)","Trim whitespace from user-supplied timezone strings","Verify the deployment image includes tzdata (alpine: add tzdata package)"],"exampleFix":"// before\ncheckTimezone(\"UTC+2\");\n// after\ncheckTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone); // e.g. \"Europe/Paris\"","handlingStrategy":"validation","validationCode":"function isValidIANATimezone(tz) {\n  if (typeof tz !== \"string\" || !tz.trim()) return false;\n  try { new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }); return true; } catch { return false; }\n}\nif (!isValidIANATimezone(tz)) tz = \"Etc/UTC\";\nsocket.emit(\"...\", { timezone: tz });","typeGuard":"function isTimezone(v: unknown): v is string { return typeof v === \"string\" && (() => { try { new Intl.DateTimeFormat(\"en-US\", { timeZone: v }); return true; } catch { return false; } })(); }","tryCatchPattern":"try { server.getTimezone(tz); } catch (e) { if (String(e.message).startsWith(\"Invalid timezone\")) { return \"Etc/UTC\"; } throw e; }","preventionTips":["Use Intl.DateTimeFormat().resolvedOptions().timeZone on the client instead of locale strings","Map fixed offsets (UTC+8) to Etc/GMT zones, remembering the sign inversion","Ensure the Docker image includes tzdata","Trim and canonicalize user-supplied timezone inputs"],"tags":["timezone","validation","dayjs","iana"],"backgroundTag":"invalid-timezone","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}