Error while using redirect in shopify remix scaffold

hey guys I am trying to redirect to this specific page if a subscription doesn’t exist but I keep getting the following error why is that -

the code I am using before the redirect is -

export const loader = async ({ request }: LoaderFunctionArgs) => {
const { session } = await authenticate.admin(request);

const billingData = await checkSubscription(session);

if (!billingData.hasPaidPlan) {
return redirect(“/app/plans”);
}

return null;
};

code in the plans page
export const loader = async ({ request }: LoaderFunctionArgs) => {
console.log(“Loading plans page”);

const { session } = await authenticate.admin(request);
const billingData = await getBillingData(session);

console.log(“Billing data:”, billingData);

const redirected = request.headers.get(“X-Subscription-Required”) === “true”;

return json({
billingData,
redirected,
});
};

could someone help me understand why this is happening thanks!

you can try redirect like:

    return json({ redirectTo: ROUTES.HOME });
  } catch (error) {
    if (error instanceof Response) {
      throw error;
    }
    console.error('Error in billing confirmation loader:', error);
    return json({ redirectTo: `${ROUTES.HOME}?${URL_SEARCH_PARAMS.BILLING.BILLING_ERROR}=true` });
  }
};

export default function BillingConfirm(): null {
  const { redirectTo } = useLoaderData<typeof loader>();
  const navigate = useNavigate();

  useEffect(() => {
    navigate(redirectTo, { replace: true });
  }, [navigate, redirectTo]);

  return null;
}

Hey, the issue is that when you use redirect("/app/plans"), it creates a new request. So any custom headers like "X-Subscription-Required" are not automatically passed to the plans page.

That’s why this line always returns false:

request.headers.get("X-Subscription-Required")

If you want to track that it was a redirect, the easiest fix is to use a query param instead:

return redirect("/app/plans?redirected=true");

and then read it like this:

const url = new URL(request.url);
const redirected = url.searchParams.get("redirected") === "true";

Or just rely on your billing check again in the plans loader and skip the flag entirely :+1: