{"record":{"id":"fa8a5d6ee0f31e68","repo":"GopeedLab/gopeed","slug":"navigation-failed","errorCode":"NAVIGATION_FAILED","errorMessage":"e.toString()","messagePattern":"e\\.toString\\(\\)","errorType":"error_code","errorClass":"WebViewRpcException","httpStatus":null,"severity":"error","filePath":"ui/flutter/lib/app/rpc/webview_rpc_service.dart","lineNumber":416,"sourceCode":"      } catch (_) {\n        // Best-effort only for the current page. The user script persists\n        // for future navigations through the native user script registry.\n      }\n    }\n  }\n\n  Future<void> goto(String url, {int? timeoutMs, String? waitUntil}) async {\n    final controller = await _controllerOrThrow();\n    final waitStrategy = _normalizeWaitUntil(waitUntil);\n    final navigation = _ensureNavigationCompleter();\n    try {\n      await controller.loadUrl(urlRequest: URLRequest(url: WebUri(url)));\n    } catch (e) {\n      if (identical(_navigation, navigation)) {\n        _navigation = null;\n      }\n      throw WebViewRpcException(\n        code: 'NAVIGATION_FAILED',\n        message: e.toString(),\n      );\n    }\n    final future = switch (waitStrategy) {\n      'domcontentloaded' => Future.any<void>([\n          _waitForDomReady(),\n          navigation.future,\n        ]),\n      _ => navigation.future,\n    };\n    if (timeoutMs == null || timeoutMs <= 0) {\n      await future;\n      return;\n    }\n    await future.timeout(\n      Duration(milliseconds: timeoutMs),\n      onTimeout: () {\n        _navigation = null;","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/ui/flutter/lib/app/rpc/webview_rpc_service.dart#L398-L434","documentation":"Thrown by WebViewRpcPageSession.goto (webview_rpc_service.dart:416) when controller.loadUrl itself throws before navigation starts. This is the native flutter_inappwebview layer rejecting the URLRequest — e.g. a URL that cannot be parsed into a WebUri — not a network failure (those arrive later via onReceivedError, error 35). The pending navigation completer is cleared and the raw exception string is wrapped as NAVIGATION_FAILED.","triggerScenarios":"Calling 'page.goto' with url: '' is caught earlier (_string), but urls like 'ftp://x', 'not a url', 'file:///nonexistent', or a URL with illegal control characters make WebUri/loadUrl throw. Also occurs when the underlying platform webview is in an invalid state.","commonSituations":"Passing a scheme the platform cannot load; building URLs by string concatenation that produces spaces or bad characters; embedded control characters from scraped HTML; WebView version changes tightening URL validation.","solutions":["Inspect the message: e.toString() contains the native error (e.g. PlatformException or URI parse failure) which names the real cause","Normalize and percent-encode the URL before sending, and default the scheme to https:// when missing","Restrict goto targets to http/https URLs you have validated with Uri.tryParse","If the page was closed concurrently, reopen the page and retry once"],"exampleFix":"// before\nawait page.goto(rawHref); // rawHref may be '/relative/path' or contain spaces\n\n// after\nfinal base = Uri.parse(currentOrigin);\nfinal target = base.resolve(rawHref.trim().replaceAll(' ', '%20'));\nawait page.goto(target.toString());","handlingStrategy":"try-catch","validationCode":"function normalizeUrl(href, base) {\n  try {\n    const u = base ? new URL(href, base) : new URL(href);\n    if (u.protocol !== 'http:' && u.protocol !== 'https:') throw new Error('unsupported scheme');\n    return u.toString();\n  } catch {\n    throw new TypeError(`invalid goto url: ${href}`);\n  }\n}","typeGuard":"function isHttpUrl(s) {\n  try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  await page.goto(url);\n} catch (e) {\n  if (e.code === 'NAVIGATION_FAILED') {\n    // message holds the native exception; fix URL or reopen page, then retry once\n    if (!isHttpUrl(url)) throw new TypeError('bad url');\n    await reopenAndGoto(url);\n  } else throw e;\n}","preventionTips":["Resolve relative hrefs against the page origin and percent-encode before goto","Restrict goto to http/https schemes validated with a URL parser","Read the wrapped native message — it distinguishes URL errors from webview-state errors"],"tags":["dart","flutter","webview","navigation","url","page-goto"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}