Versions: IBC 3.23.0, IB Gateway 10.45.1g (standalone, Linux, docker), Java 17 (zulu, bundled).
Summary
An unparseable AutoRestartTime value fails completely silently, leaving Gateway on its stored default (Auto logoff 11:45 PM local). The error message that the code does emit never reaches any log, because ibcstart.sh launches the JVM with 2>/dev/null — and Utils.logError/logException write exclusively to the captured System.err.
The operational consequence is nasty: Gateway does a full daily logoff + re-2FA at 11:45 PM local time instead of the configured soft restart. On a server whose OS timezone is not US (ours is Asia/Singapore), 11:45 PM local = 11:45 ET = the middle of US regular trading hours, so the API drops mid-session every trading day. It took byte-level debugging (decompiling the jar to confirm the message should exist, then finding the 2>/dev/null in the launch script) to discover what a single log line would have told us in seconds.
Reproduction
config.ini:
(single-digit hour — strict DateTimeFormatter.ofPattern("hh:mm a") in ConfigureAutoLogoffOrRestartTimeTask requires two digits, so this throws DateTimeParseException).
Console log shows only:
2026-06-10 23:45:11:500 IBC: Setting Auto restart time
2026-06-10 23:45:11:529 IBC: Configuration tasks completed
2026-06-10 23:45:11:529 IBC: Click button: OK
No "Auto restart time set to …", no "time setting must be hh:mm AM or hh:mm PM…" — nothing. Gateway then logs off in full every day at 11:45 PM local:
2026-06-10 23:40:30:903 IBC: detected frame entitled: U1166xxxx Exit Session Setting; event=Opened
2026-06-10 23:45:00:949 IBC: detected dialog entitled: Shutdown progress; event=Opened
IBC returned exit status 0
Finding autorestart file
autorestart file not found: full authentication will be required
Root cause of the silence
ConfigureAutoLogoffOrRestartTimeTask.run() catches the parse failure and calls Utils.logError(...) — correct so far.
Utils deliberately captures System.err at class-load time ("so that we can continue to use them even when TWS redirects System.out and System.err to its own logfile") — also fine.
- But
resources/scripts/ibcstart.sh discards the JVM's stderr in all four launch variants (lines 508–514 in 3.23.0):
"$java_path/java" $moduleAccess -cp "$ibc_classpath" ... ${mode} 2>/dev/null &
So every logError/logException banner in IBC is invisible to anyone running via the standard start script. Note #318 shows the identical silent signature (Setting Auto restart time followed immediately by Configuration tasks completed) — there the bad value was quotes rather than a single-digit hour, but the user equally got no error output and had to ask here.
Suggested fixes
Any one of these would have surfaced the problem immediately; (1) seems strictly better than the status quo in all cases:
ibcstart.sh: stop discarding stderr — redirect 2>&1 so error banners land in the same console/log as normal IBC output.
- Report configuration-task failures on the out stream — a failure that silently changes trading-session behavior (logoff vs restart) arguably shouldn't go only to a stream the official launch script throws away.
- Optionally, validate
AutoRestartTime/AutoLogoffTime eagerly at settings-load time (where logging is visible), and/or accept single-digit hours with a lenient h:mm a fallback — the strict two-digit requirement is documented but easy to miss, and the failure mode is disproportionate.
Happy to submit a PR for (1) and/or (2) if you'd take it.
Versions: IBC 3.23.0, IB Gateway 10.45.1g (standalone, Linux, docker), Java 17 (zulu, bundled).
Summary
An unparseable
AutoRestartTimevalue fails completely silently, leaving Gateway on its stored default (Auto logoff 11:45 PM local). The error message that the code does emit never reaches any log, becauseibcstart.shlaunches the JVM with2>/dev/null— andUtils.logError/logExceptionwrite exclusively to the capturedSystem.err.The operational consequence is nasty: Gateway does a full daily logoff + re-2FA at 11:45 PM local time instead of the configured soft restart. On a server whose OS timezone is not US (ours is Asia/Singapore), 11:45 PM local = 11:45 ET = the middle of US regular trading hours, so the API drops mid-session every trading day. It took byte-level debugging (decompiling the jar to confirm the message should exist, then finding the
2>/dev/nullin the launch script) to discover what a single log line would have told us in seconds.Reproduction
config.ini:(single-digit hour — strict
DateTimeFormatter.ofPattern("hh:mm a")inConfigureAutoLogoffOrRestartTimeTaskrequires two digits, so this throwsDateTimeParseException).Console log shows only:
No "Auto restart time set to …", no "time setting must be hh:mm AM or hh:mm PM…" — nothing. Gateway then logs off in full every day at 11:45 PM local:
Root cause of the silence
ConfigureAutoLogoffOrRestartTimeTask.run()catches the parse failure and callsUtils.logError(...)— correct so far.Utilsdeliberately capturesSystem.errat class-load time ("so that we can continue to use them even when TWS redirects System.out and System.err to its own logfile") — also fine.resources/scripts/ibcstart.shdiscards the JVM's stderr in all four launch variants (lines 508–514 in 3.23.0):So every
logError/logExceptionbanner in IBC is invisible to anyone running via the standard start script. Note #318 shows the identical silent signature (Setting Auto restart timefollowed immediately byConfiguration tasks completed) — there the bad value was quotes rather than a single-digit hour, but the user equally got no error output and had to ask here.Suggested fixes
Any one of these would have surfaced the problem immediately; (1) seems strictly better than the status quo in all cases:
ibcstart.sh: stop discarding stderr — redirect2>&1so error banners land in the same console/log as normal IBC output.AutoRestartTime/AutoLogoffTimeeagerly at settings-load time (where logging is visible), and/or accept single-digit hours with a lenienth:mm afallback — the strict two-digit requirement is documented but easy to miss, and the failure mode is disproportionate.Happy to submit a PR for (1) and/or (2) if you'd take it.