Skip to content

Doppelvoice v0.3.2 — HOTFIX: onefile startup crash

Choose a tag to compare

@Tianqi-Bu Tianqi-Bu released this 26 Apr 16:50

🚨 Critical hotfix. v0.3.0 and v0.3.1 .exe binaries crashed at startup with TypeError: Cannot log to objects of type 'NoneType' for all users who double-clicked the bundled .exe. v0.3.2 is the fixed binary.

Download

Doppelvoice-v0.3.2-win64.zip (60.5 MB)

SHA256: 4DCCA817B5031CCE2DB95E287C35D1C2E5FE5923B9DB2295A66B6DB48569047F

If you're on v0.3.0 or v0.3.1: download this and replace your Doppelvoice.exe. Your .env in %APPDATA%\Doppelvoice\ is preserved.

Root cause

PyInstaller's onefile + windowed bootloader (console=False) detaches stdio. Inside a bundled GUI app sys.stderr is None, but utils/log.py was doing logger.add(sys.stderr, ...) unconditionally. loguru rejects None sinks with TypeError, killing the .exe on every double-click.

This regression slipped past me because in dev mode (python -m doppelvoice) sys.stderr is always a real TTY, so the bug never surfaced until a real user fired up the bundled binary.

Fixed

  • utils/log.py setup_logging: skip the sys.stderr console sink when sys.stderr is None. The file sink under %APPDATA%\Doppelvoice\logs\ keeps working — users still get logs.
  • utils/log.py _patcher: same fix for the redact-failure fallback sys.stderr.write(...).
  • __main__.py: explicit if stream is None: continue before stdio reconfigure for clarity.

Tests

Added test_setup_logging_with_none_stderr: monkeypatches sys.stderr = None and asserts setup_logging does not raise + the file sink still produces output. Total tests now 94.

Verified

Locally retested: Doppelvoice.exe double-clicked from dist/ launches the GUI cleanly (no Tkinter exception dialog), Settings opens automatically when .env is missing, log written to %APPDATA%\Roaming\Doppelvoice\logs\doppelvoice_YYYYMMDD.log.

Lesson

v0.3.0's onefile switch was tested on the dev box where sys.stderr is a real TTY. The crash only surfaced for fresh .exe users via the windowed bootloader. Onefile + console=False deserves an explicit smoke test in CI — tracked for v0.4.

Full changelog: CHANGELOG.md