Stirling-Tools/Stirling-PDF · error · Error
errorData.error || Failed to synchronize user upgrade
Error message
errorData.error || Failed to synchronize user upgrade
What it means
Thrown by synchronizeUserUpgrade() when the POST /api/v1/user-role/promptToAuthUser backend endpoint returns a non-OK HTTP status. The function attempts to parse errorData.error from the JSON body, falling back to a generic message if parsing fails. This endpoint upgrades an anonymous user to an authenticated user in the backend's security context — the backend derives the user from the session cookie, not the request body.
Source
Thrown at frontend/editor/src/saas/services/userService.ts:41
const formData = new URLSearchParams();
if (authMethod) {
formData.append("authMethod", authMethod);
}
const response = await fetch(`${API_BASE}/user-role/promptToAuthUser`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
credentials: "include", // Include cookies for authentication
body: formData.toString(),
});
if (!response.ok) {
const errorData = await response
.json()
.catch(() => ({ error: "Failed to synchronize user upgrade" }));
throw new Error(errorData.error || "Failed to synchronize user upgrade");
}
return response.json();
};
View on GitHub (pinned to 9ef20dcab8)
Solutions
- Read errorData.error for the backend's specific error message
- Verify the session cookie is still valid — re-authenticate via Supabase and retry
- Check backend logs for /user-role/promptToAuthUser exceptions
- Ensure credentials:'include' is actually sending the cookie (check CORS Allow-Credentials header on the backend)
- Retry the sync after confirming the backend is healthy
Example fix
// before
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: "Failed to synchronize user upgrade" }));
throw new Error(errorData.error || "Failed to synchronize user upgrade");
}
// after
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: "Failed to synchronize user upgrade" }));
if (response.status === 401 || response.status === 403) {
// Session expired — re-auth and retry once
await refreshSession();
return synchronizeUserUpgrade(authMethod);
}
throw new Error(errorData.error || "Failed to synchronize user upgrade");
} Defensive patterns
Strategy: retry
Validate before calling
// Verify session is valid before syncing
const { data: { session } } = await supabase.auth.getSession();
if (!session?.access_token) {
await refreshSession();
return;
} Try / catch
try {
await synchronizeUserUpgrade(authMethod);
} catch (e) {
if (e instanceof Error && (e.message.includes('401') || e.message.includes('403'))) {
// Session expired — re-authenticate and retry once
await refreshSession();
await synchronizeUserUpgrade(authMethod);
} else {
throw e;
}
} Prevention
- Verify the session cookie is still valid (credentials:'include') before calling the sync endpoint
- Ensure the backend CORS policy includes Allow-Credentials so cookies are actually sent
- Call synchronizeUserUpgrade immediately after Supabase auth confirms the upgrade, before the session can expire
- Handle 401/403 by re-authenticating and retrying rather than showing a hard error
When it happens
Trigger: The backend session cookie has expired between the Supabase auth upgrade and this sync call; the backend security context cannot resolve the user from the cookie; the backend throws during the upgrade (e.g., user already upgraded, database error); the backend is down or returns 5xx.
Common situations: Session cookie expired (credentials:'include' sends cookies but they may be stale); backend restarted and lost session state; user's anonymous session in the backend doesn't match the newly authenticated Supabase identity; CORS preflight failure blocking the POST.
Related errors
- No SaaS session — admin must link an account before attended
- Timed out waiting for anonymous session token
- Sign up failed
- No SaaS session
- error.message
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/5c81b6b82b757054.
Report an issue: GitHub.