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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions