fix(frontend): onboarding runtime error (#10288)

## Changes 🏗️

<img width="800" alt="Screenshot 2025-07-02 at 16 43 08"
src="https://github.com/user-attachments/assets/d7cd0dd7-e671-4c5d-8ed9-6d8f56371ff5"
/>

During logout, the user state gets cleared but the onboarding provider
continues to run and tries to access onboarding.completedSteps on a null
object, causing a runtime error 😬

This mostly happens because onboarding is broken on local and dev ( the
onboarding agents don't work ), so I manually skip it after creating an
account, navigating to `/marketplace`. That makes me think that the
onboarding provider still thinks I need to onboard, and hence why this
error?

## Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  - [x] Create a new user
- [x] Instead of completing onboarding, navigate to `/marketplace` via
browser URL
- [x] logout, login/logout again few times and you don't see runtime
errors
This commit is contained in:
Ubbe
2025-07-02 18:13:22 +04:00
committed by GitHub
parent e2bd727798
commit 311bcc7751

View File

@@ -45,6 +45,7 @@ export function useOnboarding(step?: number, completeStep?: OnboardingStep) {
if (
!completeStep ||
!context.state ||
!context.state.completedSteps ||
context.state.completedSteps.includes(completeStep)
)
return;
@@ -79,22 +80,32 @@ export default function OnboardingProvider({
useEffect(() => {
const fetchOnboarding = async () => {
const enabled = await api.isOnboardingEnabled();
if (!enabled && pathname.startsWith("/onboarding")) {
router.push("/marketplace");
return;
}
const onboarding = await api.getUserOnboarding();
setState((prev) => ({ ...onboarding, ...prev }));
try {
const enabled = await api.isOnboardingEnabled();
if (!enabled && pathname.startsWith("/onboarding")) {
router.push("/marketplace");
return;
}
const onboarding = await api.getUserOnboarding();
// Redirect outside onboarding if completed
// If user did CONGRATS step, that means they completed introductory onboarding
if (
onboarding.completedSteps.includes("CONGRATS") &&
pathname.startsWith("/onboarding") &&
!pathname.startsWith("/onboarding/reset")
) {
router.push("/marketplace");
// Only update state if onboarding data is valid
if (onboarding) {
setState((prev) => ({ ...onboarding, ...prev }));
// Redirect outside onboarding if completed
// If user did CONGRATS step, that means they completed introductory onboarding
if (
onboarding.completedSteps &&
onboarding.completedSteps.includes("CONGRATS") &&
pathname.startsWith("/onboarding") &&
!pathname.startsWith("/onboarding/reset")
) {
router.push("/marketplace");
}
}
} catch (error) {
console.error("Failed to fetch onboarding data:", error);
// Don't update state on error to prevent null access issues
}
};
if (isUserLoading || !user) {
@@ -138,7 +149,12 @@ export default function OnboardingProvider({
const completeStep = useCallback(
(step: OnboardingStep) => {
if (!state || state.completedSteps.includes(step)) return;
if (
!state ||
!state.completedSteps ||
state.completedSteps.includes(step)
)
return;
updateState({
completedSteps: [...state.completedSteps, step],
@@ -148,7 +164,12 @@ export default function OnboardingProvider({
);
const incrementRuns = useCallback(() => {
if (!state || state.completedSteps.includes("RUN_AGENTS")) return;
if (
!state ||
!state.completedSteps ||
state.completedSteps.includes("RUN_AGENTS")
)
return;
const finished = state.agentRuns + 1 >= 10;
setNpsDialogOpen(finished);