flutter / flutter/flutter

[go_router_builder] Conditional redirects fail for nested GoRouteData routes with multiple ShellRoute levels

Open
#192,358 4 comments 0 reactions 0 assignees View on GitHub
p: go_router p: go_router_builder P2 package team-ecosystem triaged-ecosystem
Dominant language
Dart
Stars
179k
Forks
31.1k
PR merge metrics
PR metrics pending

Description

## Description

Using `go_router_builder` with a `GoRouteData` class that only overrides `redirect` causes an `UnimplementedError` when the redirect is conditional and returns `null` for descendant routes.

This works as expected with a manually defined `GoRoute`, but fails with generated typed routes.

The problem becomes more visible when the application contains nested `StatefulShellRoute`s and multiple levels of parent redirects.

## Environment

- `go_router: 17.5.0`
- `go_router_builder: 4.4.0`
- Flutter application running on mobile
- Nested `StatefulShellRoute` navigation

## Minimal scenario

Consider a parent route that redirects only when its exact root path is visited:

```dart
class MainRoute extends GoRouteData {
@override
String? redirect(BuildContext context, GoRouterState state) {
if (state.uri.path == '/main') {
return '/main/home';
}

// The current location is already a descendant route.
return null;
}
}
```

The intended behavior is:

```text
/main
-> redirect to /main/home

/main/home
-> redirect returns null
-> render the child route
```

Returning `null` for `/main/home` is intentional. It means that the current descendant route should be allowed to render.

The same pattern occurs with two nested shells:

```text
/main
-> /main/manage
-> /main/manage/analysis
```

For `/main/manage/analysis`, the expected redirect flow is:

```text
Main route redirect:
descendant path -> null

Manage route redirect:
descendant path -> null

Inner shell:
render the analysis branch
```

## Actual behavior

When the typed parent route returns `null`, the generated route still has `builder` and `pageBuilder` callbacks.

The route then falls through to the default `GoRouteData.build()` implementation and throws:

```text
UnimplementedError:
One of `build` or `buildPage` must be implemented.
```

Relevant stack frames:

```text
_GoRouteDataBase.build
_createGoRouteParameters.
_CustomNavigatorState._buildPageForGoRoute
```

This means that a conditional redirect-only parent route is treated as a page-building route after returning `null.

## Expected behavior

A typed route that only overrides `redirect` should be able to return `null` for descendant paths without attempting to build a page.

In particular, nested route hierarchies should support:

1. A parent route redirecting its exact root path to a default child.
2. The same parent route returning `null` for already-matched descendants.
3. Multiple nested parent redirects across multiple `StatefulShellRoute` levels.
4. Child routes and shell branches being rendered after all applicable parent redirects return `null`.

This should behave consistently with a manually defined redirect-only `GoRoute`.

## Possible implementation directions

One possible solution would be for generated typed routes to omit `builder` and `pageBuilder` when the `GoRouteData` class does not override either `build` or `buildPage`.

Another option would be for `go_router` to recognize redirect-only typed routes and exclude them from page construction when the redirect returns `null`, while still allowing their child routes to render.

The important behavior is that returning `null` from a parent redirect should mean “allow the current descendant route”, rather than invoking the default `GoRouteData.build()` implementation.

## Related issue

This appears related to the older issue:

https://github.com/flutter/flutter/issues/103368

That issue reproduces a similar `UnimplementedError` after redirecting from a typed parent route to a child route. It is closed, but the nested conditional redirect behavior described here is still reproducible with current versions.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the minimal conditional redirect scenario with nested StatefulShellRoutes, then trace the mentioned _GoRouteDataBase.build, _createGoRouteParameters, and _CustomNavigatorState._buildPageForGoRoute stack frames. Check how generated redirect-only routes expose builder and pageBuilder callbacks. Done means descendant routes render without UnimplementedError when parent redirects return null, including across multiple shell levels.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.