Skip to content

Always provide a retry handler, fix cold-boot retries, and expand logging#247

Merged
svara merged 13 commits into
mainfrom
zoe/error0fix+logging-retryable+extralogs
Jun 30, 2026
Merged

Always provide a retry handler, fix cold-boot retries, and expand logging#247
svara merged 13 commits into
mainfrom
zoe/error0fix+logging-retryable+extralogs

Conversation

@svara

@svara svara commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Reworks failed-visit retry handling and adds diagnostic logging across the navigation/session flow. Three themes:

1. Retry handling

  • Always hand the client a retry handler. Navigator.session(_:didFailRequestForVisitable:) no longer gates the handler on error.isRetryable — every failed visit now gets a retry action, letting the app/user decide.
  • Fix cold-boot retries with no topmost visitable. When session.topmostVisitable == nil, session.reload() is a no-op, so the old Retry button did nothing. The handler now falls back to session.visit(visitable, reload: true) to force a cold boot.
  • Remove isRetryable from HTTPError and HotwireNativeError (and their tests). This API was introduced after the last release, so its removal is not a breaking change for shipped consumers.

2. RedirectHandlerJSFetchRecoveryHandler

  • Renamed the handler and its error type (RedirectHandlerErrorJSFetchRecoveryError) to reflect that it recovers failed Turbo.js fetches, not just redirects. No behavioral change.

3. Logging

  • Added info/debug logging across Navigator routing/session inspection, Session.reload/resolveRedirect, ColdBootVisit (now logs the HTTP status on failure), and VisitableViewController location-state resolution.
  • Lowered WebViewPolicyManager's "no handler for navigation action" from warning to info (it falls through to .allow).

⚠️ Behavior change

Because the retry handler is now always non-nil and the default ErrorPresenter shows a Retry button iff retryHandler != nil, all error types now display a Retry button — including 404/401/403, offline, and timeout, which previously suppressed it. This is intentional, but worth calling out for release notes.

Testing

  • Removed the isRetryable unit tests (property no longer exists); updated JSFetchRecoveryHandlerTests for the rename.
  • Added NavigatorRetryHandlerTests covering the new behavior: the handler is always provided (even for a previously non-retryable 404), retries the visit directly with a cold boot when there is no topmost visitable, and reloads the session otherwise.

zoejessica and others added 12 commits February 17, 2026 07:24
Log the resolve request, its outcome (no redirect, same-origin, or
cross-origin), and—crucially—the error details in the catch blocks
of Session.resolveRedirect which were previously silent.
ColdBootVisit silently swallowed the status code when canceling non-2xx
responses. Now logs at warning level with the status code and URL so
errors like 404s are visible in the log files.
* main: (55 commits)
  Set `lazyLoadTabs` to `true` by default.
  Split HotwireLogger into focused files under Logging/
  Move and expand custom logger tests
  Remove obsolete logger.
  Enable debug logging automatically for debug builds in the Demo app.
  Remove obsolete `Logging` in favor of `HotwireLogger`.
  Allow injection of a custom logger
  Make redirect-resolution timeout configurable
  Add ScriptMessage.isReady accessor
  Consolidate Turbo.js status codes into a TurboError type.
  Use `HotwireNativeError` instead of `Error`.
  Fix refresh_historical_location restoring from snapshot cache
  Cancel leaked WKWebView navigations in test simulator
  Move default logger to config variable
  Remove Hotwire.config.debugLoggingEnabled
  Rename logDestination: LogDestination to logger: HotwireLogger
  Remove explicit type
  Log destination
  Add configuration to lazy load tabs
  Make HotwireTab.image optional to mimic UITab API
  ...
- Correct the web-view-recreation skip log: it fires when the process
  is not terminated, not when a topmost visitable is missing
- Fix typo and clarify the no-parent reload skip message
- Drop a stray whitespace-only line
@svara
svara force-pushed the zoe/error0fix+logging-retryable+extralogs branch from c1f53ca to 5b59e68 Compare June 30, 2026 12:04
Covers the new Navigator behavior: a retry handler is always provided
(even for previously non-retryable errors), the handler retries the
visit directly with a cold boot when there is no topmost visitable, and
falls back to reloading the session otherwise.
@svara
svara marked this pull request as ready for review June 30, 2026 12:09
@svara svara self-assigned this Jun 30, 2026
@svara
svara merged commit 9ff1ee9 into main Jun 30, 2026
1 of 3 checks passed
@svara
svara deleted the zoe/error0fix+logging-retryable+extralogs branch June 30, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants