Repository: gradio-app/gradio

Issue:
Bug Report: Authentication-Enabled Gradio App Stuck on Loading Indicator
### Describe the bug

Description:
In the latest version of our Gradio app, when authentication is enabled and deployed to Cloud Run, the loading indicator remains indefinitely, and the app never reaches the sign-in page. This issue did not appear in previous versions. like gradio 5.14.0

Steps to Reproduce:
	1.	Deploy the Gradio app with authentication enabled to Cloud Run.
	2.	Access the app via the provided URL.
	3.	Observe that the loading indicator is restored indefinitely and the sign-in page never appears.

Expected Behavior:
The app should transition from the loading state to the authentication page, allowing users to sign in.

Actual Behavior:
The app remains stuck on the loading screen and never reaches the sign-in page.

Environment:
	•	Gradio Version: 5.15.0
	•	Deployment Platform: GCP Cloud Run
	•	Date Observed: February 2025

Additional Context:
	•	The issue is new to this version and was not present in previous releases.
	•	No related errors appear in the Cloud Run logs.
	•	If authentication is disabled, the app loads as expected.

### Have you searched existing issues?  🔎

- [x] I have searched and found no existing issues

### Reproduction

```python
import gradio as gr



 app.launch(
        server_name="0.0.0.0",
        server_port=8080,
        auth=("admin", "pass")   
    )

```


### Screenshot

_No response_

### Logs

```shell

```

### System Info

```shell
gradio==5.15.0
```

### Severity

I can work around it

Hints from issue comments:
@freddyaboulton: Hi @ferdinandl007 - if you revert to an older version of gradio does the app load properly?@freddyaboulton: Nvm can reproduce even without Cloud Run@ferdinandl007: Yeah, it works when I revert back to an older version

Solution patch:
diff --git a/.changeset/bumpy-rivers-allow.md b/.changeset/bumpy-rivers-allow.md
new file mode 100644
index 000000000..e4edf7016
--- /dev/null
+++ b/.changeset/bumpy-rivers-allow.md
@@ -0,0 +1,5 @@
+---
+"gradio": patch
+---
+
+fix:Fix Auth
diff --git a/.changeset/floppy-onions-lick.md b/.changeset/floppy-onions-lick.md
new file mode 100644
index 000000000..45eb41312
--- /dev/null
+++ b/.changeset/floppy-onions-lick.md
@@ -0,0 +1,5 @@
+---
+"gradio": patch
+---
+
+fix:Fix DF Postprocess for tuples
diff --git a/.changeset/many-ways-flash.md b/.changeset/many-ways-flash.md
new file mode 100644
index 000000000..b972c7dbb
--- /dev/null
+++ b/.changeset/many-ways-flash.md
@@ -0,0 +1,6 @@
+---
+"@gradio/dataframe": patch
+"gradio": patch
+---
+
+feat:Fix spacing issue with `gr.Dataframe` in Safari
diff --git a/.changeset/odd-geckos-yawn.md b/.changeset/odd-geckos-yawn.md
new file mode 100644
index 000000000..e21fdaebd
--- /dev/null
+++ b/.changeset/odd-geckos-yawn.md
@@ -0,0 +1,6 @@
+---
+"@gradio/dataframe": minor
+"gradio": minor
+---
+
+feat:Prevent scrolling when the dataframe cell menu is open
diff --git a/.changeset/olive-pants-judge.md b/.changeset/olive-pants-judge.md
new file mode 100644
index 000000000..6dd72a30c
--- /dev/null
+++ b/.changeset/olive-pants-judge.md
@@ -0,0 +1,6 @@
+---
+"@gradio/client": patch
+"gradio": patch
+---
+
+fix:quick_fix_client
diff --git a/client/js/src/client.ts b/client/js/src/client.ts
index 3b8191e81..5654dd630 100644
--- a/client/js/src/client.ts
+++ b/client/js/src/client.ts
@@ -75,7 +75,12 @@ export class Client {
 		const stripSlashes = (str: string): string => str.replace(/^\/+|\/+$/g, "");
 		let root_path = stripSlashes(new URL(this.config.root).pathname);
 		let url_path = stripSlashes(new URL(url).pathname);
-		let page = stripSlashes(url_path.substring(root_path.length));
+		let page: string;
+		if (!url_path.startsWith(root_path)) {
+			page = "";
+		} else {
+			page = stripSlashes(url_path.substring(root_path.length));
+		}
 		return this.get_page_config(page);
 	}
 	get_page_config(page: string): Config {
@@ -84,7 +89,7 @@ export class Client {
 		}
 		let config = this.config;
 		if (!(page in config.page)) {
-			throw new Error(`Page ${page} not found`);
+			page = "";
 		}
 		return {
 			...config,
diff --git a/gradio/components/dataframe.py b/gradio/components/dataframe.py
index 86b797c92..d29415f72 100644
--- a/gradio/components/dataframe.py
+++ b/gradio/components/dataframe.py
@@ -337,6 +337,8 @@ class Dataframe(Component):
             if not isinstance(value, list):
                 raise ValueError("output cannot be converted to list")
             if not isinstance(value[0], list):
+                if isinstance(value[0], tuple):
+                    return [list(v) for v in value]
                 return [[v] for v in value]
             return value
         else:
diff --git a/gradio/routes.py b/gradio/routes.py
index 5e3de34e7..4c9d9b40f 100644
--- a/gradio/routes.py
+++ b/gradio/routes.py
@@ -570,6 +570,11 @@ class App(FastAPI):
                     "auth_message": blocks.auth_message,
                     "space_id": blocks.space_id,
                     "root": root,
+                    "page": {"": {"layout": {}}},
+                    "pages": [""],
+                    "components": [],
+                    "dependencies": [],
+                    "current_page": "",
                 }
 
             try:
diff --git a/js/dataframe/shared/Table.svelte b/js/dataframe/shared/Table.svelte
index 47f6b3f91..569c22704 100644
--- a/js/dataframe/shared/Table.svelte
+++ b/js/dataframe/shared/Table.svelte
@@ -883,6 +883,7 @@
 		class="table-wrap"
 		class:dragging
 		class:no-wrap={!wrap}
+		class:menu-open={active_cell_menu || active_header_menu}
 		style="height:{table_height}px"
 		on:keydown={(e) => handle_keydown(e)}
 		role="grid"
@@ -1007,6 +1008,8 @@
 				bind:actual_height={table_height}
 				bind:table_scrollbar_width={scrollbar_width}
 				selected={selected_index}
+				disable_scroll={active_cell_menu !== null ||
+					active_header_menu !== null}
 			>
 				{#if label && label.length !== 0}
 					<caption class="sr-only">{label}</caption>
@@ -1207,6 +1210,10 @@
 		border-radius: var(--table-radius);
 	}
 
+	.table-wrap.menu-open {
+		overflow: hidden;
+	}
+
 	.table-wrap:focus-within {
 		outline: none;
 	}
diff --git a/js/dataframe/shared/VirtualTable.svelte b/js/dataframe/shared/VirtualTable.svelte
index bb2653e80..d013065ee 100644
--- a/js/dataframe/shared/VirtualTable.svelte
+++ b/js/dataframe/shared/VirtualTable.svelte
@@ -10,6 +10,7 @@
 	export let start = 0;
 	export let end = 20;
 	export let selected: number | false;
+	export let disable_scroll = false;
 	let height = "100%";
 
 	let average_height = 30;
@@ -41,6 +42,11 @@
 			return;
 		}
 
+		// force header height calculation first
+		head_height =
+			viewport.querySelector(".thead")?.getBoundingClientRect().height || 0;
+		await tick();
+
 		const { scrollTop } = viewport;
 		table_scrollbar_width = viewport.offsetWidth - viewport.clientWidth;
 
@@ -256,29 +262,32 @@
 </script>
 
 <svelte-virtual-table-viewport>
-	<table
-		class="table"
-		bind:this={viewport}
-		bind:contentRect={viewport_box}
-		on:scroll={handle_scroll}
-		style="height: {height}; --bw-svt-p-top: {top}px; --bw-svt-p-bottom: {bottom}px; --bw-svt-head-height: {head_height}px; --bw-svt-foot-height: {foot_height}px; --bw-svt-avg-row-height: {average_height}px; --max-height: {max_height}px"
-	>
-		<thead class="thead" bind:offsetHeight={head_height}>
-			<slot name="thead" />
-		</thead>
-		<tbody bind:this={contents} class="tbody">
-			{#if visible.length && visible[0].data.length}
-				{#each visible as item (item.data[0].id)}
-					<slot name="tbody" item={item.data} index={item.index}>
-						Missing Table Row
-					</slot>
-				{/each}
-			{/if}
-		</tbody>
-		<tfoot class="tfoot" bind:offsetHeight={foot_height}>
-			<slot name="tfoot" />
-		</tfoot>
-	</table>
+	<div>
+		<table
+			class="table"
+			class:disable-scroll={disable_scroll}
+			bind:this={viewport}
+			bind:contentRect={viewport_box}
+			on:scroll={handle_scroll}
+			style="height: {height}; --bw-svt-p-top: {top}px; --bw-svt-p-bottom: {bottom}px; --bw-svt-head-height: {head_height}px; --bw-svt-foot-height: {foot_height}px; --bw-svt-avg-row-height: {average_height}px; --max-height: {max_height}px"
+		>
+			<thead class="thead" bind:offsetHeight={head_height}>
+				<slot name="thead" />
+			</thead>
+			<tbody bind:this={contents} class="tbody">
+				{#if visible.length && visible[0].data.length}
+					{#each visible as item (item.data[0].id)}
+						<slot name="tbody" item={item.data} index={item.index}>
+							Missing Table Row
+						</slot>
+					{/each}
+				{/if}
+			</tbody>
+			<tfoot class="tfoot" bind:offsetHeight={foot_height}>
+				<slot name="tfoot" />
+			</tfoot>
+		</table>
+	</div>
 </svelte-virtual-table-viewport>
 
 <style type="text/css">
@@ -342,4 +351,8 @@
 		z-index: var(--layer-1);
 		overflow: hidden;
 	}
+
+	.table.disable-scroll {
+		overflow: hidden !important;
+	}
 </style>


Test patch:
diff --git a/test/components/test_dataframe.py b/test/components/test_dataframe.py
index 90d39f49e..48712fe1b 100644
--- a/test/components/test_dataframe.py
+++ b/test/components/test_dataframe.py
@@ -167,6 +167,14 @@ class TestDataframe:
             "metadata": None,
         }
 
+        dataframe_output = gr.Dataframe(headers=["one", "two", "three"])
+        output = dataframe_output.postprocess([(1, 2, 3), (4, 5, 6)]).model_dump()
+        assert output == {
+            "headers": ["one", "two", "three"],
+            "data": [[1, 2, 3], [4, 5, 6]],
+            "metadata": None,
+        }
+
     def test_dataframe_postprocess_all_types(self):
         df = pd.DataFrame(
             {