Skip to content

Config-task errors (e.g. unparseable AutoRestartTime) are silently discarded: ibcstart.sh redirects JVM stderr to /dev/null #364

Description

@open2026-04

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:

AutoRestartTime=2:00 PM

(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

  1. ConfigureAutoLogoffOrRestartTimeTask.run() catches the parse failure and calls Utils.logError(...) — correct so far.
  2. 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.
  3. 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:

  1. ibcstart.sh: stop discarding stderr — redirect 2>&1 so error banners land in the same console/log as normal IBC output.
  2. 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.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions