Skip to content

edge: don't take the host process down when the WebView2 controller/environment can't be created (session 0) - #87

Open
peterpla wants to merge 1 commit into
jchv:masterfrom
peterpla:fix/session0-nil-controller
Open

edge: don't take the host process down when the WebView2 controller/environment can't be created (session 0)#87
peterpla wants to merge 1 commit into
jchv:masterfrom
peterpla:fix/session0-nil-controller

Conversation

@peterpla

@peterpla peterpla commented Aug 17, 2026

Copy link
Copy Markdown

What

On a non-visible window station — a process in Windows session 0 with no
interactive desktop (a service, an S4U scheduled task, a boot task) — WebView2
controller creation completes with a success HRESULT but a nil controller.
CreateCoreWebView2ControllerCompleted guards only the HRESULT, then dereferences
the controller, so the host process panics on a nil pointer inside webview.New.
EnvironmentCompleted has the same shape via log.Fatalf, which also exits the
process. Neither lets the caller fall back to a non-GUI path.

Fixes #86.

Change

pkg/edge/chromium.go — wire the async failures into the nil-return contract
New already has (New → nil when CreateWithOptionsEmbed returns false),
with no public signature change:

  • Test the HRESULT with int32(res) < 0 (HRESULT is signed 32-bit) and guard
    controller/env for nil in the two completion callbacks; on failure, record an
    embedErr and set inited to unblock Embed's message pump instead of
    log.Fatalf/dereferencing nil.
  • Embed returns false when embedErr is set (matching its existing
    log.Printf(...); return false for other setup failures), so New returns nil.

Note on the width: the observed failure HRESULT is 0x8000401a, which is negative
as int32 but not as int64 — so the original int64(res) < 0 never fired for
a real failure code. Narrowing to int32 makes the HRESULT branch work; the nil
guard additionally covers a nil out-pointer returned alongside a success HRESULT.

Verification

Standalone program calling only webview.New(false), launched on a session-0
window station (over PowerShell Direct), Windows 10 + WebView2 Evergreen
151.0.4129.86:

  • Before: panic (nil pointer dereference) at chromium.go:190, process exit 2.
  • After: webview.New returns nil, process exit 0.

Both runs confirmed a non-visible (session-0) window station.

Scope

A smaller change is possible if preferred: the controller nil-guard alone fixes the
crash, and the log.Fatalf → error-return part can be dropped.

@jchv

jchv commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Woah, I don't think I ever expected anyone to try go-webview2 in Session 0. I don't really have a policy for LLM patches yet but this looks trivial enough that it is probably not worth worrying about. I should probably run this locally before merging it but it does LGTM.

@peterpla

Copy link
Copy Markdown
Author

Headless browser-based webcam image captures on a schedule (e.g., sunrise to sunset, every 5 minutes), auto-start as session-0 lets captures continue before the user logs in. Not an obvious scenario :) Thanks for your work on go-webview2!

…an't be created

On a non-visible window station (Windows session 0, no interactive desktop),
controller creation completes with a success HRESULT but a nil controller.
CreateCoreWebView2ControllerCompleted checked only the HRESULT and then
dereferenced the controller, panicking the process inside webview.New;
EnvironmentCompleted log.Fatalf'd on its failure path. Guard both pointers,
record the failure, unblock Embed's message pump, and return false from Embed so
New returns nil and the caller can fall back.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@peterpla
peterpla force-pushed the fix/session0-nil-controller branch from 525372f to d46c29b Compare August 17, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CreateCoreWebView2ControllerCompleted dereferences a nil controller / log.Fatalfs the host on a non-interactive window station (session 0)

2 participants