TRPC server recieves... html?

I'm at a hackaton right now, where i wanted to give t3 a go. I now receive this error as i want to use a mutation to change a clerk user in the server side. you got any ideas?
No description
14 Replies
Tamás Soós
Tamás Soós12mo ago
Could you link to some code?
quest1onmark
quest1onmark12mo ago
dini mami yes sure, one minute
quest1onmark
quest1onmark12mo ago
GitHub
GitHub - jonasschultheiss/nosh-nodes
Contribute to jonasschultheiss/nosh-nodes development by creating an account on GitHub.
quest1onmark
quest1onmark12mo ago
the hackathon is over, so please don‘t overanalyze it. i‘m just wondering based on interest
Josh
Josh12mo ago
This is an absurdly terrible question. I'm more than willing to help but please make it a good question
Tamás Soós
Tamás Soós12mo ago
Yeah I have to agree. Which page where you on? What did you do to get the error, etc...?
quest1onmark
quest1onmark12mo ago
/ redirects to clerk, sfter the login the afterAuth of middleware will redirect you to /sign-up /sign-up has a resct-hook-form form, where i want to get name, username and yearsAtWork from the user. i then wanted to update the clerk user using the trcp on the server side. the client sends the correctly formated and populated json to the backend but the backend then throws the error as seen in the provided picture whats most likely the cause is that i messed up something with the trcp setup to me it‘s magic and i don‘t understand the workings behind it yet so i cant really give a direction on what went wrong
Tamás Soós
Tamás Soós12mo ago
The issue was in the middleware. Your custom redirect logic doesn't work well with tRPC. tRPC is meant to handle JSON formatted data, but the redirect will send some html down the wire. I suppose you wouldn't want to redirect in the middle of the mutation anyway, so one way to handle it would be to add one more condition to your redirect logic like this:
import { authMiddleware, redirectToSignIn } from "@clerk/nextjs";
import { redirect } from "next/navigation";
import { NextResponse } from "next/server";

// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
export default authMiddleware({
afterAuth(auth, req, _evt) {
if (!auth.userId && !auth.isPublicRoute) {
redirectToSignIn({ returnBackUrl: req.url });
}
if (
auth.userId &&
!auth.user?.firstName &&
!auth.user?.lastName &&
!auth.user?.username &&
!auth.user?.publicMetadata.yearsAtWork &&
req.nextUrl.pathname !== "/sign-up" &&
!req.nextUrl.pathname.match("/(api|trpc)(.*)") // <-- Don't redirect if it's a tRPC API call
) {
const signUp = new URL("/sign-up", req.url);
return NextResponse.redirect(signUp);
}
},
});

export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
import { authMiddleware, redirectToSignIn } from "@clerk/nextjs";
import { redirect } from "next/navigation";
import { NextResponse } from "next/server";

// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
export default authMiddleware({
afterAuth(auth, req, _evt) {
if (!auth.userId && !auth.isPublicRoute) {
redirectToSignIn({ returnBackUrl: req.url });
}
if (
auth.userId &&
!auth.user?.firstName &&
!auth.user?.lastName &&
!auth.user?.username &&
!auth.user?.publicMetadata.yearsAtWork &&
req.nextUrl.pathname !== "/sign-up" &&
!req.nextUrl.pathname.match("/(api|trpc)(.*)") // <-- Don't redirect if it's a tRPC API call
) {
const signUp = new URL("/sign-up", req.url);
return NextResponse.redirect(signUp);
}
},
});

export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
quest1onmark
quest1onmark12mo ago
ah i see, thats unfurtunate. thanks a lot for looking into this did you catch this because you know how trpc works or did you have to play around because it makes sense retrospectively but i'd never have guessed that this would be it.
Josh
Josh12mo ago
If you've used trpc long enough it's something you'll learn, but if you're new it can definitely get you. What I did to solve this in my system was add a default onError client side, and redirect there where I get a tRPC UNAUTHORIZED error My protected procedure wrapper
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
db: ctx.db,
session: { ...ctx.session, user: ctx.session.user },
},
});
});
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
db: ctx.db,
session: { ...ctx.session, user: ctx.session.user },
},
});
});
Client side query client with default
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
mutations: {
onError: (e) => {
const error = e as TRPCClientError<AppRouter>;
if (
error.data?.code === "UNAUTHORIZED" ||
error.message === "UNAUTHORIZED"
)
router.replace(
`/sign-in?callbackUrl=${window.location.pathname}`,
);
},
},
queries: {
staleTime: 5000,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
}),
);
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
mutations: {
onError: (e) => {
const error = e as TRPCClientError<AppRouter>;
if (
error.data?.code === "UNAUTHORIZED" ||
error.message === "UNAUTHORIZED"
)
router.replace(
`/sign-in?callbackUrl=${window.location.pathname}`,
);
},
},
queries: {
staleTime: 5000,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
}),
);
Tamás Soós
Tamás Soós12mo ago
I had to play around with it a little, but it was mostly about trying to find where the html could come from. After finding the custom redirect response in the middleware I was pretty confident that's the issue. Oh and getting it to reproduce took longer than finding the cause. The global style import was wrong, then after getting the keys from clerk, it wasn't redirecting me to the login. I was just stuck on the home page. So I had to add a sign in / out button.
quest1onmark
quest1onmark12mo ago
huh ok well… that worked in my machiene anyway, thank you for putting in the time
Tamás Soós
Tamás Soós12mo ago
You're welcome.
Want results from more Discord servers?
Add your server