Sahag98
Sahag982mo ago

GetUserIdentity null

Hi there, I have a list of queries that run for it's corresponding page in my nextjs 14 web app. Inside each query I have a getUser hook that will check the identity and return the user associated with it:
import { QueryCtx } from "@/convex/_generated/server";

export async function GetUser(ctx: QueryCtx) {
const identity = await ctx.auth.getUserIdentity();

if (!identity) {
throw new Error("Unauthenticated call to mutation");
}
const user = await ctx.db
.query("users")
.withIndex("byExternalId", (q) => q.eq("externalId", identity.subject))
.unique();
if (!user) {
throw new Error("Unauthenticated user call");
}

return user;
}
import { QueryCtx } from "@/convex/_generated/server";

export async function GetUser(ctx: QueryCtx) {
const identity = await ctx.auth.getUserIdentity();

if (!identity) {
throw new Error("Unauthenticated call to mutation");
}
const user = await ctx.db
.query("users")
.withIndex("byExternalId", (q) => q.eq("externalId", identity.subject))
.unique();
if (!user) {
throw new Error("Unauthenticated user call");
}

return user;
}
However there are instances where the identity is sometimes null, therefore throwing that error and interrupting the user. How can I implement this in a better way? I feel like I'm doing something wrong here... Thank you!
3 Replies
Convex Bot
Convex Bot2mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
ballingt
ballingt2mo ago
How did you implement auth? You probably want to avoid making the queries until you've sent in the auth token. Once an auth token has been sent in the auth.getUserIdentity() will not be null.
Sahag98
Sahag98OP2mo ago
I'm using convex and clerk. The whole app is wrapped inside a convexclerkprovider Layout.tsx
import "./globals.css";
import { ConvexClientProvider } from "./convex-provider";
import { Toaster } from "@/components/ui/toaster";
import { SidebarProvider } from "@/components/ui/sidebar";
import NextTopLoader from "nextjs-toploader";
import { TooltipProvider } from "@/components/ui/tooltip";

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ConvexClientProvider>
<html lang="en">
<body className="max-w-[2800px] flex items-center justify-center">
<SidebarProvider>
<TooltipProvider>
{/* <SidebarTrigger /> */}
{/* <AppSidebar /> */}
<NextTopLoader color="black" />
{children}
<Toaster />
</TooltipProvider>
</SidebarProvider>
</body>
</html>
</ConvexClientProvider>
);
}
import "./globals.css";
import { ConvexClientProvider } from "./convex-provider";
import { Toaster } from "@/components/ui/toaster";
import { SidebarProvider } from "@/components/ui/sidebar";
import NextTopLoader from "nextjs-toploader";
import { TooltipProvider } from "@/components/ui/tooltip";

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ConvexClientProvider>
<html lang="en">
<body className="max-w-[2800px] flex items-center justify-center">
<SidebarProvider>
<TooltipProvider>
{/* <SidebarTrigger /> */}
{/* <AppSidebar /> */}
<NextTopLoader color="black" />
{children}
<Toaster />
</TooltipProvider>
</SidebarProvider>
</body>
</html>
</ConvexClientProvider>
);
}
And the provider:
"use client";

import { ClerkProvider, useAuth } from "@clerk/clerk-react";
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { ConvexReactClient } from "convex/react";
import { ReactNode } from "react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<ClerkProvider
publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}
>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
</ClerkProvider>
);
}
"use client";

import { ClerkProvider, useAuth } from "@clerk/clerk-react";
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { ConvexReactClient } from "convex/react";
import { ReactNode } from "react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<ClerkProvider
publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}
>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
</ClerkProvider>
);
}

Did you find this page helpful?