Repository navigation
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listfound in release: 3.38Found to occur in 3.38Found to occur in 3.38found in release: 3.40Found to occur in 3.40Found to occur in 3.40has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packagepackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-webWeb applications specificallyWeb applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
Description
What package does this bug report belong to?
go_router
What target platforms are you seeing this bug on?
Web
Have you already upgraded your packages?
Yes
Dependency versions
pubspec.lock
go_router:
dependency: "direct main"
description:
name: go_router
sha256: eff94d2a6fc79fa8b811dde79c7549808c2346037ee107a1121b4a644c745f2a
url: "https://pub.dev"
source: hosted
version: "17.0.1"
go_router_builder:
dependency: "direct dev"
description:
name: go_router_builder
sha256: "8f1dd8cc23850dba4223104231682a9410576720cb24693fb0eb925c49b2abe3"
url: "https://pub.dev"
source: hosted
version: "4.1.3"
Steps to reproduce
- Define a route with a path parameter, e.g.
/user/:id. - Navigate internally with
context.go('/user/${Uri.encodeComponent("foo bar")}'). - Refresh the page or enter
/user/foo%20bardirectly in the browser. - Compare
GoRouterState.pathParameters['id']and the browser’s address bar value in both cases.
Expected results
- Consistent decoding: Path parameters should be decoded (or not) in the same way regardless of navigation source. Developers should not need to special-case deep links vs in-app navigation.
- Stable browser URL: On web, the address bar should not be rewritten unless the app explicitly performs a redirect. The URL the user enters should remain visible as-is.
Suggested Resolution
- Decide on a single, consistent policy for URL decoding (either always decode once, or always leave encoded).
- Ensure that on web, GoRouter does not rewrite the browser’s address bar unless a redirect is explicitly configured.
- Consider exposing helpers in
path_utilsfor safe, balanced encode/decode handling.
Actual results
- Path parameters are decoded for deep links but remain encoded for in-app navigation.
- Browser URL is silently replaced with a canonicalized/decoded version, even without redirects.
Impact
- Developers cannot reliably extract parameters without risking double-decoding or mismatched values.
- Users see the URL they entered change unexpectedly, which is confusing and can break copy/paste or bookmarking workflows.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:go_router/go_router.dart';
void main() {
usePathUrlStrategy();
runApp(const MyApp());
}
final _router = GoRouter(
routes: [
GoRoute(path: '/', builder: (context, state) => const HomePage()),
GoRoute(
path: '/item/:value',
builder: (context, state) {
final value = state.pathParameters['value'] ?? '';
return DetailPage(value: value);
},
),
],
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'GoRouter Web Minimal',
routerConfig: _router,
theme: ThemeData(useMaterial3: true),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _controller = TextEditingController(text: 'foo bar');
@override
void initState() {
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _goToDetail() {
var raw = _controller.text.trim();
raw = Uri.encodeComponent(raw);
if (raw.isEmpty) {
return;
}
// Encode to keep the URL valid on web.
context.go('/item/${Uri.encodeComponent(raw)}');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _controller,
decoration: const InputDecoration(
labelText: 'Enter raw id',
border: OutlineInputBorder(),
),
onSubmitted: (_) => _goToDetail(),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: _goToDetail,
child: const Text('Go to second page'),
),
],
),
),
),
);
}
}
class DetailPage extends StatelessWidget {
final String value;
const DetailPage({super.key, required this.value});
@override
Widget build(BuildContext context) {
final encoded = value;
final decoded = Uri.decodeComponent(encoded);
return Scaffold(
appBar: AppBar(title: const Text('Second Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Encoded: $encoded',
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
Text(
'Decoded: $decoded',
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
],
),
),
);
}
}
Flutter Doctor output
Doctor output
[√] Flutter (Channel stable, 3.38.5, on Microsoft Windows [Version 10.0.26100.7462], locale en-CH)
[√] Windows Version (11 Pro 64-bit, 24H2, 2009)
[√] Android toolchain - develop for Android devices (Android SDK version 36.0.0-rc5)
[√] Chrome - develop for the web
[√] Connected device (2 available)
[√] Network resourcesMetadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listfound in release: 3.38Found to occur in 3.38Found to occur in 3.38found in release: 3.40Found to occur in 3.40Found to occur in 3.40has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packagepackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-webWeb applications specificallyWeb applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
Activity
darshankawar commentedon Jan 5, 2026
Seeing same behavior on latest sdk versions.
apinilabs-pascal commentedon Jul 21, 2026
any update on this?
apinilabs-pascal commentedon Jul 22, 2026
same issue for query parameter by the way.
[web] Stop percent-decoding URLs written to browser history (flutter#…
github-actions commentedon Oct 17, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.[web] Stop percent-decoding URLs written to browser history (flutter#…