MetaMask / MetaMask/metamask-mobile

[Bug][Major]: Android in-app browser reloads page after history.replaceState + history.pushState

Open
#31,176 1 comment 0 reactions 0 assignees View on GitHub
external-contributor INVALID-ISSUE-TEMPLATE needs-triage regression-prod-7.79.1 Sev1 ta-ai-fixable ta-needs-engineer-escalation ta-triaged team-mobile-platform type-bug
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

### Describe the bug

MetaMask Mobile Android in-app browser performs a full page reload after simple same-origin History API navigation.

**This is a critical issue** because it breaks links navigation in any SPA. For example, Vue SPA applications using `vue-router` with `createWebHistory` can unexpectedly reload during normal client-side navigation.

I created a very minimal reproduction without React, Vue, wallet connection, or any dapp logic. It only uses `history.replaceState()` and `history.pushState()`. This is the same underlying mechanism used in frameworks like React, Vue, etc., so this MetaMask bug affects normal client-side navigation in SPA applications.

### Minimal reproduction

index.html:
```html




History Repro



Loaded at:


Step 1: / -> /1


Step 2: /1 -> /2


document.getElementById('loadedAt').textContent = new Date().toLocaleTimeString('en-GB', { hour12: false });

function onClick1() {
window.history.replaceState({}, '', '/');
window.history.pushState({}, '', '/1');
}

function onClick2() {
window.history.replaceState({}, '', '/1');
window.history.pushState({}, '', '/2');
}

```

### Steps to reproduce

1. Open MetaMask Mobile on Android.
2. Open the in-app browser.
3. Open this URL: https://phenomenal-dasik-74938a.netlify.app/
4. Click button `Step 1`.
5. Click button `Step 2`.

### Actual behavior

After tapping Step 1 and then Step 2, the page reloads.

The `Loaded at` value changes, which means the current document was destroyed and loaded again.

### Expected behavior

The URL should change using the History API, but the current document should stay alive.

The page should not reload.

### Where was this bug found?

Live version (from official store)

### Version

7.79.1

### Build number

5225

### Build type

None

### Device

Xiaomi 13T Pro

### Operating system

Android

### Severity

**This is a critical issue** because it breaks links navigation in any SPA.
This affects all android users of all SPA websites (in 2026 basically all websites are SPA).

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the report's minimal index.html in the MetaMask Mobile Android in-app browser using version 7.79.1, then inspect the in-app browser's History API navigation handling. Verify the behavior after the replaceState and pushState steps on the provided URL. Done means same-origin navigation changes the URL without destroying and reloading the current document.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, javascript, react-native, typescript
Domain
mobile, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.