Description
The session callback in lib/auth-config.ts replaces session.user with a hand-built object, discarding the standard Auth.js fields:
async session ({ session, token }): Promise<any> {
if (token) {
(session.user as any) = {
id: token.id as string,
walletAddress: (token as any).walletAddress as string,
username: (token as any).username as string,
};
}
return session;
}
session.user.name, email, and image are gone, so any useSession() consumer that reads those (e.g. the nav avatar) gets undefined. Compounding this, the jwt callback only copies fields when user is present (initial sign-in) and ignores the trigger: "update" / session argument entirely. components/avatar-upload.tsx calls:
await updateSession({ user: { ...session.user, image: item.url } })
to reflect a newly uploaded avatar in the nav, but because the jwt callback drops the update payload and the session callback re-derives user from the stale token, the update is a silent no-op — the avatar never updates without a full reload.
More info
- File:
app/lib/auth-config.ts (jwt callback approx. lines 88-96, session callback approx. lines 97-106)
- File:
app/components/avatar-upload.tsx (approx. lines 53-55)
- In the
session callback, spread rather than replace: session.user = { ...session.user, id, walletAddress, username } and map the stored avatar to image.
- In the
jwt callback, handle trigger === "update" by merging the provided session payload (e.g. token.picture = session.user.image).
- Add a test asserting
useSession().update({ user: { image } }) is reflected in the next auth() session without a reload.
Description
The
sessioncallback inlib/auth-config.tsreplacessession.userwith a hand-built object, discarding the standard Auth.js fields:session.user.name,email, andimageare gone, so anyuseSession()consumer that reads those (e.g. the nav avatar) getsundefined. Compounding this, thejwtcallback only copies fields whenuseris present (initial sign-in) and ignores thetrigger: "update"/sessionargument entirely.components/avatar-upload.tsxcalls:to reflect a newly uploaded avatar in the nav, but because the
jwtcallback drops the update payload and thesessioncallback re-derivesuserfrom the stale token, the update is a silent no-op — the avatar never updates without a full reload.More info
app/lib/auth-config.ts(jwtcallback approx. lines 88-96,sessioncallback approx. lines 97-106)app/components/avatar-upload.tsx(approx. lines 53-55)sessioncallback, spread rather than replace:session.user = { ...session.user, id, walletAddress, username }and map the stored avatar toimage.jwtcallback, handletrigger === "update"by merging the providedsessionpayload (e.g.token.picture = session.user.image).useSession().update({ user: { image } })is reflected in the nextauth()session without a reload.