{"record":{"id":"32611e13996789fc","repo":"GopeedLab/gopeed","slug":"webview-page-handle-is-not-initialized","errorCode":null,"errorMessage":"webview page handle is not initialized","messagePattern":"webview page handle is not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/engine/webview/runtime.go","lineNumber":426,"sourceCode":"\nfunc (p *PageHandle) Content() (string, error) {\n\tvalue, err := p.Execute(`() => document.documentElement ? document.documentElement.outerHTML : \"\"`)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn parseString(value), nil\n}\n\nfunc (p *PageHandle) Close() error {\n\tif p == nil || p.runtime == nil {\n\t\treturn nil\n\t}\n\treturn p.runtime.closePage(p.id)\n}\n\nfunc (p *PageHandle) page() (Page, error) {\n\tif p == nil || p.runtime == nil {\n\t\treturn nil, fmt.Errorf(\"webview page handle is not initialized\")\n\t}\n\treturn p.runtime.getPage(p.id)\n}\n\nfunc (p *PageHandle) poll(opts WaitOptions, fn func() (any, bool, error)) (any, bool, error) {\n\ttimeout := time.Duration(defaultWaitTimeoutMS(opts.TimeoutMS)) * time.Millisecond\n\tpollInterval := time.Duration(defaultPollIntervalMS(opts.PollIntervalMS)) * time.Millisecond\n\tdeadline := time.Now().Add(timeout)\n\tfor {\n\t\tvalue, matched, err := fn()\n\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t}\n\t\tif matched {\n\t\t\treturn value, true, nil\n\t\t}\n\t\tif time.Now().After(deadline) {\n\t\t\treturn nil, false, nil","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/engine/webview/runtime.go#L408-L444","documentation":"PageHandle.page() is the internal accessor used by cookie/navigation-facing methods (GetCookies, SetCookie, DeleteCookie, ClearCookies). It fails when the handle is nil or its runtime reference is nil — i.e. a zero-value PageHandle or one not produced by a successful Runtime open. Execute-based methods (URL, Content, Evaluate) do not go through this check.","triggerScenarios":"Declaring var p webview.PageHandle (or page := &webview.PageHandle{}) and calling p.GetCookies(); storing a handle in a struct field that was never assigned from Open's return value; ignoring Open's error and using the nil/zero handle it returned.","commonSituations":"Optional page fields in helper structs that stay nil on early-exit paths; copying PageHandle values instead of pointers during refactors; tests constructing handles directly.","solutions":["Always obtain the PageHandle from a successful runtime Open/NewPage call and check that call's error first","Nil-check the handle before calling cookie-related methods","Pass *PageHandle by pointer and never construct it manually"],"exampleFix":"// before\nvar page PageHandle;\nawait page.getCookies(); // -> webview page handle is not initialized\n// after\nconst [page, err] = await runtime.open(url);\nif (err) throw err;\nconst cookies = await page.getCookies();","handlingStrategy":"type-guard","validationCode":"if page == nil {\n    return errors.New(\"open a page before calling cookie APIs\")\n}","typeGuard":"// Go: PageHandle is ready only when obtained from a successful open\nfunc pageReady(p *webview.PageHandle) bool {\n    return p != nil // runtime is unexported; a non-nil handle from Open is always initialized\n}","tryCatchPattern":null,"preventionTips":["Always check the error returned by the open call before using the handle","Never construct PageHandle manually or copy it by value","Store *PageHandle (pointer) so nil-checks are meaningful"],"tags":["webview","nil-guard","page","browser-automation"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}