I'm deploying a Next.js 14 app on Google Cloud Run, protected by IAP (Identity-Aware Proxy) and fronted by a Load Balancer. Everything works fine when the user is logged in with a Google account. However, after a period of inactivity (when the Google session expires), calling a Server Action results in a 401 Unauthorized response from IAP — but no error is thrown in the client-side code, even when wrapped in a try/catch.
Working scenario:
- User logs in via Google.
- Clicks a button that triggers a Server Action.
- Server Action executes successfully.
Broken scenario:
- User session expires (e.g., after being idle for a while).
- User clicks the same button.
- The Server Action silently fails — no error is caught, and the return value is undefined.
Example code:
'use client';
import { myServerAction } from './actions';
export default function MyComponent() {
const handleClick = async () => {
try {
const result = await myServerAction();
console.log('Result:', result);
} catch (err) {
console.error('Caught error:', err); // This never runs
}
};
return <button onClick={handleClick}>Call Server Action</button>;
}
'use server';
export async function myServerAction() {
// Some logic here
return 'Hello from server';
}
Observations:
- When session is valid: result is "Hello from server".
- When session is expired: result is undefined, and no error is caught.
- IAP logs show a 401 Unauthorized response.
Questions:
- Why doesn't Next.js throw an error when the Server Action fails due to IAP 401?
- Is there a way to detect this failure on the client side?
- What is the recommended approach to handle session expiration when using Server Actions with IAP?
- Should I wrap Server Actions with a custom fetch layer instead?