n8n Schedule Trigger चुकीच्या वेळी का चालतो?
n8n मध्ये Schedule Trigger चुकीच्या वेळी चालत असल्यास TZ, GENERIC_TIMEZONE आणि workflow timezone तपासा. तीनपैकी एक सेटिंग चुकीची असल्याने वेळ तासांनी चुकू शकतो.
n8n schedule trigger चुकीच्या वेळी का कार्यान्वित होतो
n8n schedule trigger चुकीच्या वेळी कार्यान्वित होतो, कारण n8n आपला timezone तीन स्वतंत्र ठिकाणांहून वाचतो. यापैकी एक ठिकाण दुरुस्त केल्यास समस्येचा केवळ काही भाग सुटतो. ही तीन ठिकाणे म्हणजे container चे स्वतःचे TZ variable, instance default GENERIC_TIMEZONE आणि स्वतंत्र workflow मध्ये सेट केलेला timezone. ही तिन्ही मूल्ये एकदाच सेट करा. त्यानंतर तयार केलेले प्रत्येक schedule अपेक्षित वेळी कार्यान्वित होईल.
प्रथम एक चुकीचा समज दूर करा. नवीन self-hosted n8n UTC (coordinated universal time) मध्ये schedule करत नाही. Official image मध्ये TZ सेट केलेले नसल्यामुळे container clock UTC असतो. Scheduling हा स्वतंत्र स्तर आहे. GENERIC_TIMEZONE साठी n8n चा documented default America/New_York आहे (August 2026 पर्यंत). त्यामुळे कोणताही बदल न केलेला instance आपले Schedule Triggers New York time नुसार कार्यान्वित करतो. म्हणून वापरकर्त्यांनी सांगितलेला time offset त्यांचे UTC पासूनचे स्वतःचे अंतर दर्शवत नाही. Berlin मधील एखाद्या मालकाने 06:00 ची वेळ मागितल्यास trigger स्थानिक वेळेनुसार 12:00 वाजता कार्यान्वित होतो. United States ने daylight saving time लागू केलेले असते आणि Europe ने अद्याप केलेले नसते अशा March मधील आठवड्यांत तो 11:00 वाजता कार्यान्वित होतो.
तीन timezone स्तर आणि त्यांपैकी कोणता लागू होतो
TZ हा container मधील operating system timezone आहे. n8n च्या documentation नुसार ही variable system timezone सेट करते. त्यामुळे date सारख्या scripts आणि commands कडून मिळणारे परिणाम नियंत्रित होतात. Container मध्ये date काय दाखवते, container log line वर कोणता timestamp नोंदवला जातो, Code node मध्ये new Date() काय परत करते आणि तेथे चालवलेल्या कोणत्याही shell script ला कोणता timezone दिसतो, हे ती ठरवते. Schedule Trigger कधी execute होईल यावर तिचा परिणाम होत नाही.
GENERIC_TIMEZONE हा n8n instance timezone आहे. Documentation मध्ये त्याला n8n instance timezone म्हटले आहे आणि Cron सारख्या schedule nodes साठी तो महत्त्वाचा असल्याचे नमूद केले आहे. येथे Cron म्हणजे वेळेवर आधारित scheduling साठीची standard syntax. n8n मध्ये ती Schedule Trigger मधील Custom (Cron) पर्याय म्हणून उपलब्ध आहे.
Workflow timezone प्रत्येक workflow साठी स्वतंत्रपणे सेट केला जातो. Canvas वर workflow उघडा. वरच्या उजव्या कोपऱ्यातील तीन dots निवडा. त्यानंतर Settings निवडा आणि Timezone value बदला. हा बदल त्या workflow साठी GENERIC_TIMEZONE ला override करतो.
Schedule Trigger साठी क्रम निश्चित आहे. Workflow मध्ये timezone सेट केला असल्यास n8n तो वापरते. तो नसल्यास GENERIC_TIMEZONE मधील instance timezone वापरला जातो. तोही उपलब्ध नसल्यास n8n चा built-in default America/New_York वापरला जातो. या निर्णयातील कोणत्याही टप्प्यावर TZ विचारात घेतले जात नाही.
तुमच्या nodes मधील dates साठी उत्तर code कोणते clock वापरते यावर अवलंबून असते. n8n expressions मागे वापरले जाणारे date library Luxon, n8n timezone वापरते. त्यामुळे $now आणि $today हे trigger प्रमाणेच workflow-then-instance क्रमाचे पालन करतात. Code node मधील साधे JavaScript new Date() operating system कडे विचारते. त्यामुळे ते TZ चे पालन करते. यामुळेच येथे बहुतेक गोंधळ होतो: trigger योग्य प्रकारे execute होऊ शकतो, पण workflow ने लिहिलेला प्रत्येक timestamp काही तासांनी चुकीचा असू शकतो.
Compose फाइलमध्ये तिन्ही सेट करा
फाइलमध्ये TZ आणि GENERIC_TIMEZONE एकमेकांच्या जवळ ठेवा, म्हणजे कोणी एक सेट करून दुसरे विसरणार नाही. खालील fragment हा कार्यरत सेवेतील timezone-संबंधित भाग आहे. फाइलचा उर्वरित भाग, reverse proxy आणि certificate, HTTPS मागे VPS वर self-hosted n8n मधून घेतला आहे.
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- GENERIC_TIMEZONE=Europe/Berlin
- TZ=Europe/Berlin
- N8N_RUNNERS_ENABLED=true
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:हे docker compose restart वापरून नव्हे, तर docker compose up -d वापरून लागू करा. Restart केल्यावर त्याच container ला तो तयार करताना वापरलेल्या environment सह पुन्हा सुरू केले जाते. त्यामुळे फाइलमधील बदल running process पर्यंत पोहोचत नाहीत. up -d बदललेले environment ओळखते आणि container पुन्हा तयार करते. ही values inline ठेवण्याऐवजी env file मध्ये ठेवल्यास हाच recreate नियम लागू होतो. ती फाइल कुठून read केली जाते यासाठी Compose env file आणि secrets हाताळणी मार्गदर्शक पहा.
Region/City मध्ये IANA (Internet Assigned Numbers Authority) zone name वापरा, जसे Europe/Berlin किंवा America/Sao_Paulo. या नावांमध्ये त्या ठिकाणाचे daylight saving नियम असतात. त्यामुळे स्थानिक घड्याळानुसार offset बदलतो. Etc/GMT+5 सारखे fixed-offset name ऋतूनुसार कधीही बदलत नाही. त्याचा sign तुम्ही अपेक्षा कराल त्याच्या उलट असतो. LC_ALL=C TZ=Etc/GMT+5 date +%z चालवा; त्यावर -0500 छापले जाईल. अशी नावे टाळा.
यापैकी फक्त एक सेट केल्याने समस्या अर्धवटच का सुटते
फक्त GENERIC_TIMEZONE सेट केल्यास Schedule Trigger तुम्हाला हव्या असलेल्या तासाला चालतो, पण operating system कडून माहिती वाचणाऱ्या सर्व गोष्टी UTC वरच राहतात. new Date().toString() कॉल करणारा Code node UTC string परत करतो, container log मधील ओळी UTC मध्ये नोंदवल्या जातात आणि system clock वरून तयार केलेले कोणतेही file name चुकीच्या मध्यरात्रीला बदलते.
फक्त TZ सेट केल्यास याउलट घडते. docker compose exec n8n date तुमची स्थानिक वेळ दाखवते आणि ते यशस्वी झाल्यासारखे दिसते, पण Schedule Trigger अजूनही America/New_York वर असतो आणि तुम्ही मागितलेल्या तासापेक्षा सहा तास आधी किंवा नंतर चालतो. या प्रकारात सर्वाधिक वेळ वाया जातो, कारण बहुतेक लोक प्रथम जी तपासणी करतात ती आता यशस्वी होते.
Workflow timezone सेट केल्यानंतर GENERIC_TIMEZONE बदलल्यास तो workflow हा बदल दुर्लक्षित करतो. Workflow मधील मूल्याला प्राधान्य मिळते आणि कोणी त्या workflow ची settings उघडेपर्यंत ते तसेच राहते. शेजारील workflow योग्य वेळी चालत असताना एखादा workflow अनोख्या वेळी चालत असेल, तर त्यामागे जवळजवळ नेहमी हेच कारण असते.
अंदाज करण्याऐवजी घड्याळे तपासा
Host आणि container यांची थेट तुलना करा.
date
docker compose exec n8n date
docker compose exec n8n printenv TZ GENERIC_TIMEZONETZ सेट केल्यानंतर पहिल्या दोन commands ने समान wall-clock time दाखवला पाहिजे. printenv उपलब्ध असलेल्या प्रत्येक variable साठी एक ओळ दाखवते. त्यामुळे output मध्ये दोन ओळी असतील तर दोन्ही सेट आहेत. एक ओळ असेल तर तुम्ही अर्धवट दुरुस्त केलेल्या स्थितीकडे पाहत आहात.
आता workflow च्या आतून n8n ला स्वतः तपासा. कारण workflow-level timezone कोणता आहे हे container shell सांगू शकत नाही. चुकीची वर्तणूक करणाऱ्या workflow मध्ये Code node जोडा आणि Execute Workflow वापरून तो एकदा चालवा.
return [
{
json: {
n8n_time: $now.toISO(),
n8n_zone: $now.zoneName,
system_time: new Date().toString(),
},
},
];n8n_zone हा या workflow चा Schedule Trigger वापरणारा zone आहे. तो workflow-then-instance क्रमाने आधीच resolve केलेला असतो. त्यामुळे तो या प्रश्नाचे थेट उत्तर देतो. system_time मध्ये TZ मधून मिळालेला container चा स्वतःचा zone असतो. हा Code node नवीन workflow मध्ये न चालवता चुकीची वर्तणूक करणाऱ्या workflow मध्येच चालवा. कारण workflow-level setting workflow सोबत राहते. ही दोन values वेगवेगळी असल्यास, एकही config file न उघडता समस्या सापडली आहे.
Schedule Trigger नोडमधील Cron expressions
Schedule Trigger मध्ये सेकंदांपासून महिन्यांपर्यंतचे निश्चित intervals उपलब्ध आहेत. यांमध्ये समाविष्ट नसलेल्या वेळापत्रकांसाठी Custom (Cron) वापरा. Cron expression workflow च्या resolved timezone मध्ये वाचले जाते. त्यामुळे 0 6 * * * म्हणजे त्या zone मधील 06:00, 06:00 UTC नव्हे. crontab guru मधील पाच-field expression जशीच्या तशी paste करता येते. n8n optional seconds field देखील स्वीकारते. Documentation मधील field table मध्ये हा field प्रथम दिला आहे: second, minute, hour, day of month, month, day of week.
Offset स्वतःहून कधीही encode करू नका. UTC instance वर 06:00 Berlin वेळ मिळवण्यासाठी 0 4 * * * लिहिणे हिवाळ्यात योग्य आहे. मात्र संपूर्ण उन्हाळ्यात ते एक तासाने चुकीचे ठरेल, कारण हिवाळ्यात Berlin UTC+1 आणि उन्हाळ्यात UTC+2 वर चालते. Zone सेट करा आणि तुम्हाला अपेक्षित असलेला स्थानिक hour लिहा.
02:30 साठी निश्चित केलेल्या job वर daylight saving चा परिणाम
स्थानिक wall-clock वेळ ही हमखास निश्चित instant नसते. वर्षातून दोनदा एक तास नाहीसा होतो आणि एक तास पुन्हा येतो. या वेळांमध्ये schedule केलेल्या कोणत्याही job वर त्याचा परिणाम होतो. कोणतेही n8n वापरल्याशिवाय, कोणत्याही Linux box वर date वापरून हे पाहता येते.
LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30'date: invalid date '2027-03-28 02:30'ही command मधील typo नाही. 2027-03-28 रोजी Berlin चे घड्याळ थेट 02:00 वरून 03:00 वर जाते. त्यामुळे त्या दिवशी स्थानिक 02:30 ही वेळ अस्तित्वातच नसते आणि date तिला instant मध्ये रूपांतरित करण्यास नकार देते. स्थानिक 02:30 ला आधारित job चालवण्यासाठी कोणताही moment उपलब्ध नसतो. शेजारच्या वेळा मात्र योग्य आहेत: date -d '2027-03-28 01:30' चे resolution CET म्हणून आणि date -d '2027-03-28 03:30' चे resolution CEST म्हणून होते.
शरद ऋतूतील बदल याच्या उलट असतो. 2027-10-31 रोजी Berlin चे घड्याळ 03:00 वरून पुन्हा 02:00 वर येते. त्यामुळे 02:30 ही वेळ दोनदा येते.
LC_ALL=C TZ=Europe/Berlin date -d '2027-10-31 02:30 CEST' '+%s'
LC_ALL=C TZ=Europe/Berlin date -d '2027-10-31 02:30 CET' '+%s'1824942600
1824946200हे दोन वेगवेगळे instants आहेत. दोन्हींना स्थानिक 02:30 असे म्हणतात आणि त्यांच्यात 3600 seconds चे अंतर असते. त्या वेळेला निश्चित केलेली job दोनदा चालू शकते किंवा कोणीही निवडलेली नसलेली वेळ वापरून एकदाच चालू शकते. Billing run किंवा backup rotation साठी यापैकी कोणताही परिणाम योग्य नाही. Schedule ही वेळेची window टाळून ठेवा. युरोप आणि उत्तर अमेरिकेतील बहुतेक time zones मध्ये धोकादायक band स्थानिक 00:00 ते 03:00 असा असतो.
पायाभूत सुविधा UTC मध्ये शेड्यूल करा आणि लोकांना स्थानिक वेळ दाखवा
timezone मुळे होणारी दोन कामे वेगळी ठेवणे हा प्रमाणित उपाय आहे. मशीनना स्थिर कालावधी आवश्यक असतो. लोकांना वाचता येईल अशी वेळ आवश्यक असते.
- ज्या कामांवर कोणी लक्ष ठेवत नाही, त्या workflow साठी timezone म्हणून UTC सेट करा. Backup, cache warming, log shipping आणि report generation यांचा समावेश येथे होतो. UTC मध्ये वर्षातील प्रत्येक दिवशी दोन run मधील अंतर तुम्ही लिहिलेल्या अंतराइतकेच असते, कारण UTC मध्ये daylight saving नाही.
- एखादी व्यक्ती वाचणार असलेल्या कामांसाठी schedule UTC मध्ये ठेवा आणि display च्या टप्प्यावर वेळेचे रूपांतर करा. यासाठी एक expression पुरेसे आहे:
{{ $now.setZone('Europe/Berlin').toFormat('yyyy-MM-dd HH:mm') }}message body मध्ये स्थानिक वेळ ठेवते, तर trigger स्थिर राहतो.
हीच विभागणी n8n च्या बाहेरही लागू होते. तुमच्या automation चा काही भाग VPS वरील systemd service आणि timer म्हणून चालत असल्यास, त्यातील OnCalendar ओळ system timezone मध्ये वाचली जाते. हा स्वतंत्र setting असलेला चौथा clock आहे. प्रत्येक scheduler UTC वर ठेवल्यास चार वेगवेगळे नियम लक्षात ठेवण्याऐवजी एकच नियम लक्षात ठेवावा लागतो. कालावधीचा सारांश देणाऱ्या कोणत्याही कामासाठी हे महत्त्वाचे आहे. कारण कालच्या आकड्यांसाठी n8n AI agent workflow वापरल्यास, कोणत्या zone नुसार त्याचे निराकरण झाले यावर अवलंबून वेगळ्या 24 तासांचा कालावधी वापरला जाऊ शकतो.
अपयशाची कारणे आणि दिसणारे आउटपुट
सर्व गोष्टी सुमारे सहा तासांच्या फरकाने चालतात. GENERIC_TIMEZONE सेट केलेले नव्हते, त्यामुळे अंगभूत डीफॉल्ट America/New_York लागू होते. docker compose exec n8n printenv GENERIC_TIMEZONE काहीही आउटपुट देत नाही. ते सेट करा आणि कंटेनर पुन्हा तयार करा.
तुम्ही Compose फाइल संपादित केली, पण काहीही बदलले नाही. तुम्ही docker compose restart चालवले, त्यामुळे कंटेनरमध्ये त्याचे मूळ environment कायम राहिले. docker compose up -d चालवा आणि नंतर docker compose exec n8n printenv TZ वापरून पडताळा.
ट्रिगर योग्य आहे, पण timestamps चुकीचे आहेत. फक्त GENERIC_TIMEZONE सेट केलेले आहे. Code node मधील new Date() अजूनही operating system कडून UTC वाचते. TZ ला त्याच value वर सेट करा आणि कंटेनर पुन्हा तयार करा.
एक workflow instance setting कडे दुर्लक्ष करते. त्या workflow च्या settings मध्ये स्वतःचा timezone सेट केलेला आहे. तो GENERIC_TIMEZONE पेक्षा प्राधान्याने लागू होतो. Canvas उघडा, three dots निवडा, Settings, Timezone.
या वर्षी एकदा daily job दोनदा चालले किंवा एक दिवस वगळला. त्याची scheduled hour daylight saving transition च्या कालावधीत येते. ती hour बदला किंवा तो workflow UTC वर हलवा.
FAQ
माझा n8n schedule trigger चुकीच्या तासाला का सुरू होतो?
Workflow गृहीत धरलेल्या timezone ऐवजी वेगळा timezone वापरत आहे. Workflow मध्ये timezone सेट केलेला असल्यास n8n workflow timezone वापरते. तो नसल्यास GENERIC_TIMEZONE मधील instance timezone वापरते. तेही नसल्यास n8n चे अंगभूत default America/New_York वापरले जाते. GENERIC_TIMEZONE सेट न केलेल्या self-hosted instance मध्ये schedules New York time नुसार चालतात, UTC नुसार नाहीत. त्यामुळे UTC पासून तुमच्या स्वतःच्या फरकाइतका offset क्वचितच जुळतो. docker compose exec n8n printenv GENERIC_TIMEZONE चालवा. कोणतेही output न आल्यास ते कधीही सेट केले गेले नव्हते.
n8n मधील TZ आणि GENERIC_TIMEZONE मध्ये काय फरक आहे?
TZ हा container मधील operating system timezone आहे. तो container मध्ये date काय परत करते, container log lines वर कोणते timestamps दिसतात, Code node मध्ये new Date() काय परत करते आणि त्यात चालवलेल्या कोणत्याही script ला काय दिसते हे नियंत्रित करतो. GENERIC_TIMEZONE हा n8n instance timezone आहे. Schedule nodes आणि $now सारख्या Luxon expressions हाच timezone वापरतात. एकच value सेट केल्यास trigger योग्य वेळी सुरू होऊ शकतो पण timestamps चुकीचे दिसू शकतात, किंवा timestamps योग्य असू शकतात पण trigger अपेक्षेपेक्षा काही तास दूर सुरू होऊ शकतो. दोन्हींची value समान ठेवा.
Workflow timezone किंवा GENERIC_TIMEZONE पैकी काय सेट करावे?
संपूर्ण instance साठी default म्हणून GENERIC_TIMEZONE सेट करा. एखादा workflow प्रत्यक्षात दुसऱ्या zone शी संबंधित असल्यासच त्यासाठी per-workflow setting वापरा. Workflow value ही instance value वर प्राधान्य घेते. GENERIC_TIMEZONE मध्ये नंतर केलेले बदल ती value बदलत नाहीत. त्यामुळे विसरलेला per-workflow override काही महिन्यांनंतर शोधणे कठीण होते.
घड्याळ बदलताना 02:30 ला scheduled job चे काय होते?
तो local time एकतर अस्तित्वातच राहत नाही किंवा दोनदा येतो. त्या दिवशी Berlin clock 02:00 वरून 03:00 वर उडी मारत असल्यामुळे LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30' date: invalid date '2027-03-28 02:30' परत करते. 2027-10-31 रोजी त्याच wall-clock reading चे दोन instants शी mapping होते आणि त्यांच्यात एक तासाचे अंतर असते. Scheduled work 00:00 ते 03:00 या local band बाहेर ठेवा, किंवा workflow UTC वर सेट करा आणि व्यक्तीला वाचण्यासाठी आवश्यक असेल तेव्हाच local time मध्ये रूपांतर करा.