Skip to content

Case Sensitivity Issue in go_router When Manually Entering URLs with Incorrect Case in Path Segments #162487

@Kashif-Asghar60

Description

@Kashif-Asghar60

Steps to reproduce

When using go_router with GetMaterialApp.router for Flutter web navigation, manually entering a URL with incorrect case in the last path segment causes an assertion error. However, URLs with incorrect case in earlier path segments are automatically corrected and work as expected.

For example:

❌ Fails: http://localhost:58569/#/STORE/cart (incorrect case in the second last segment)

✅ Works: http://localhost:58569/#/store/CART (auto case correction happens)

✅ Works: http://localhost:58569/#/about

✅ Works: http://localhost:58569/#/ABOUT (auto case correction happens)

✅ Works: http://localhost:58569/#/abouT. (auto case correction happens)

The error occurs with the following assertion failure:
Assertion failed: file:///Users/m1nespace/.pub-cache/hosted/pub.dev/go_router-14.7.1/lib/src/match.dart:235:12 uri.path.startsWith(newMatchedLocation) is not true

Steps to Reproduce

You can Clone the repository to reproduce the issue:

git clone https://github.com/Kashif-Asghar60/go_router_case_sensitivity_issue.git

Run the app in a web browser.

Manually enter the following URLs in the browser's address bar:

http://localhost:58569/#/STORE/cart (fails)

http://localhost:58569/#/store/CART (works)

http://localhost:58569/#/about (works)

http://localhost:58569/#/ABOUT (works)

http://localhost:58569/#/abouT (works)

Observe the red screen with the assertion error when the last path segment has incorrect case.

Expected results

URLs with incorrect case in any path segment should be automatically corrected and navigate to the correct route.

For example, http://localhost:58569/#/STORE/cart should redirect to http://localhost:58569/#/store/cart.

Actual results

URLs with incorrect case in earlier path segments are automatically corrected and work as expected.

URLs with incorrect case in the last path segment cause an assertion error:
Assertion failed: uri.path.startsWith(newMatchedLocation) is not true

Code sample

Code sample

routes.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'screens.dart'; 

final GoRouter router = GoRouter(
  navigatorKey: Get.key, 
  initialLocation: '/', 
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomePage(),
      routes: [
        GoRoute(
          path: 'store',
          builder: (context, state) {
            final args = state.uri.queryParameters['name'] ?? 'Guest';
            return StorePage(name: args);
          },
          routes: [
            GoRoute(
              path: 'products',
              builder: (BuildContext context, GoRouterState state) {
                return StoreProductsPage();
              },
            ),
            GoRoute(
              path: 'cart',
              builder: (BuildContext context, GoRouterState state) {
                return StoreCartPage();
              },
            ),
            GoRoute(
              path: 'checkout',
              builder: (BuildContext context, GoRouterState state) {
                return StoreCheckoutPage();
              },
            ),
          ],
        ),
        GoRoute(
          path: 'contact',
          builder: (context, state) => ContactPage(),
        ),
        GoRoute(
          path: 'about',
          builder: (context, state) => AboutPage(),
        ),
        GoRoute(
          path: 'profile/:id',
          builder: (context, state) {
            final id = state.pathParameters['id']!;
            return ProfilePage(userId: id);
          },
        ),
      ],
    ),
  ],
  errorBuilder: (context, state) => Scaffold(
    appBar: AppBar(title: const Text('Error')),
    body: const Center(child: Text('Page not found')),
  ),
redirect: (context, state) {
  print("=== Redirect Callback Triggered ===");
  print("Original URI: ${state.uri}");
  print("Original Path: ${state.uri.path}");

  // Normalize the path to lowercase
  final path = state.uri.path.toLowerCase();
  print("Lowercased Path: $path");

  if (path != state.uri.path) {
    print("Path has changed. Redirecting to: ${state.uri.replace(path: path)}");
    return state.uri.replace(path: path).toString();
  } else {
    print("No change in path. No redirection needed.");
  }

  return null;
},
);


main.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'authcontroller.dart';
import 'routes.dart'; // Import your GoRouter configuration
import 'screens.dart'; // Import your screens

void main() {
  Get.put(AuthController()); // Initialize your GetX controller
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp.router(
      title: 'Flutter Web Navigation',
      // Use GoRouter for navigation
      routerDelegate: router.routerDelegate,
      routeInformationParser: router.routeInformationParser,
      routeInformationProvider: router.routeInformationProvider,
      debugShowCheckedModeBanner: false,
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration Image Image

Logs

Logs Image

Flutter Doctor output

Doctor output
                                        
[✓] Flutter (Channel stable, 3.24.5, on macOS 15.1 24B83 darwin-arm64, locale en-US)
    • Flutter version 3.24.5 on channel stable at /Users/m1nespace/Developer/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision dec2ee5c1f (3 months ago), 2024-11-13 11:13:06 -0800
    • Engine revision a18df97ca5
    • Dart version 3.5.4
    • DevTools version 2.37.3

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    • Android SDK at /Users/m1nespace/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16C5032a
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)

[✓] VS Code (version 1.96.4)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.102.0

[✓] Connected device (4 available)
    • Kashif Asghar’s iPhone (mobile) • 00008101-000D28962269001E • ios            • iOS 18.1.1 22B91
    • macOS (desktop)                 • macos                     • darwin-arm64   • macOS 15.1 24B83
      darwin-arm64
    • Mac Designed for iPad (desktop) • mac-designed-for-ipad     • darwin         • macOS 15.1 24B83
      darwin-arm64
    • Chrome (web)                    • chrome                    • web-javascript • Google Chrome
      132.0.6834.160

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listfound in release: 3.27Found to occur in 3.27found in release: 3.29Found to occur in 3.29has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.platform-webWeb applications specificallyr: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions