{"record":{"id":"597edfe529f4a1fd","repo":"GopeedLab/gopeed","slug":"invalid-navigation-state","errorCode":null,"errorMessage":"invalid navigation state","messagePattern":"invalid navigation state","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/webview/goprovider/provider.go","lineNumber":409,"sourceCode":"\t}\n\treturn false\n}\n\nfunc parseURL(raw string) (*url.URL, error) {\n\treturn url.Parse(raw)\n}\n\nfunc (p *pageWrapper) navigationState() (navigationState, error) {\n\tvalue, err := p.Execute(`() => ({\n\t\turl: String(location.href || \"\"),\n\t\treadyState: document.readyState || \"\",\n\t})`)\n\tif err != nil {\n\t\treturn navigationState{}, err\n\t}\n\tstateMap, ok := value.(map[string]any)\n\tif !ok {\n\t\treturn navigationState{}, fmt.Errorf(\"invalid navigation state\")\n\t}\n\tstate := navigationState{}\n\tif urlValue, ok := stateMap[\"url\"].(string); ok {\n\t\tstate.URL = urlValue\n\t}\n\tif readyValue, ok := stateMap[\"readyState\"].(string); ok {\n\t\tstate.ReadyState = readyValue\n\t}\n\treturn state, nil\n}\n\nfunc (p *pageWrapper) dispatch(fn func(w webview.WebView) error) error {\n\tp.mu.Lock()\n\tif p.closed {\n\t\tp.mu.Unlock()\n\t\treturn fmt.Errorf(\"webview page is closed\")\n\t}\n\tw := p.view","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/internal/webview/goprovider/provider.go#L391-L427","documentation":"navigationState() (internal/webview/goprovider/provider.go:402) evaluates an inline JS expression that returns an object literal {url, readyState} and requires the decoded result to be map[string]any. If Execute yields anything else — typically nil after the JS context was destroyed mid-navigation — this error returns. It is the shape-check between the JS bridge and the Go struct.","triggerScenarios":"Polling navigation state exactly while the page navigates or is destroyed (eval returns null/undefined); an Execute plumbing fault where the callback resolves with a non-object JSON value; a closed or crashed render process making the eval return nothing.","commonSituations":"Happens transiently during waitForNavigation polling windows on fast navigations; persistent when the page crashes or the bridge callback name is misconfigured so results never arrive in object form.","solutions":["Retry the state read after a short delay — transient nulls during navigation are the common cause","Ensure the page is still open and the navigation has settled before querying state","If persistent, verify the Execute path end-to-end with a trivial expression like '() => 1' to isolate bridge problems"],"exampleFix":"// before\nstate, err := page.NavigationState() // \"invalid navigation state\" mid-navigation\n\n// after\nvar state map[string]any\nfor attempt := 0; attempt < 3; attempt++ {\n    v, err := page.Execute(`() => ({ url: location.href, readyState: document.readyState })`)\n    if err == nil {\n        if m, ok := v.(map[string]any); ok {\n            state = m\n            break\n        }\n    }\n    time.Sleep(200 * time.Millisecond) // let the navigation settle\n}","handlingStrategy":"retry","validationCode":"// Tolerant state read: retry while the JS context settles\nfunc readNavState(page enginewebview.Page) (map[string]any, error) {\n    for attempt := 0; attempt < 3; attempt++ {\n        v, err := page.Execute(`() => ({ url: String(location.href || \"\"), readyState: document.readyState || \"\" })`, nil)\n        if err == nil {\n            if m, ok := v.(map[string]any); ok {\n                return m, nil\n            }\n        }\n        time.Sleep(200 * time.Millisecond)\n    }\n    return nil, errors.New(\"navigation state unavailable\")\n}","typeGuard":"func isNavState(v any) bool {\n    m, ok := v.(map[string]any)\n    return ok && m[\"url\"] != nil\n}","tryCatchPattern":"v, err := page.Execute(expr, nil)\nif err == nil {\n    if m, ok := v.(map[string]any); !ok {\n        // transient during navigation: back off once, then fail\n        time.Sleep(250 * time.Millisecond)\n        v, err = page.Execute(expr, nil)\n    }\n}","preventionTips":["Expect null results during navigation windows; design polls to tolerate them","Verify the Execute bridge with a trivial expression when this error persists","Do not query state on a page that may already be closed"],"tags":["webview","navigation","type-mismatch","js-bridge"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}