Matt Luo
Matt Luo10mo ago

Uncaught Error: Unauthenticated call to function

I am trying to stand up a happy path of using a single Convex query function to authenticate a user with Clerk, select from the users table, and then select from the userSettings table.
10 Replies
Matt Luo
Matt LuoOP10mo ago
Observed Behavior: On the front end of my page, http://localhost:3000/two-part-query-function, I get this error message: Unhandled Runtime Error Error: [CONVEX Q(userSettings:getUserSettingsByTokenIdentifier)] [Request ID: 30e901867821f71e] Server Error Uncaught Error: Unauthenticated call to function at handler (../convex/userSettings.ts:108:4) Called by client Source src/app/(try-convex)/two-part-query-function/page.tsx (30:5) @ api 28 | 29 | const selectUserSettingsData = useQuery(
30 | api.userSettings.getUserSettingsByTokenIdentifier,
| ^ 31 | ); 32 | 33 | // // Type guard function to check if the query is still loading In the Chrome console, the app prints this debugging message: [CONVEX Q(userSettings:getUserSettingsByTokenIdentifier)] [LOG] 'server identity' null In the Chrome Network tab, sync, messages, there is not Authenticate message. See this Vercel deployment for this issue: https://crystal-txt-web-git-feature-conv-63a4bb-matts-projects-82cbe13a.vercel.app/two-part-query-function Interestingly, in page.tsx, if I comment out this selectUserSettingsData variable and keep the variable, authUserIdentity, const authUserIdentity = useQuery(api.userSettings.queryAuthUserIdentity, {}); This query is completely successful. In the Chrome Network tab, sync, messages, there is indeed a Authenticate message with a lengthy string in the "value". value: "eyJhbGciOiJSUz..." See this Vercel deployment for this observation: https://crystal-txt-kf4lyk8m7-matts-projects-82cbe13a.vercel.app/two-part-query-function I am relatively new to Convex, but I don't see anything fundamentally different about how this query gets the authentication from Clerk. This queryAuthUserIdentity is simpler and only has two jobs to do which is to authenticate with Clerk and get the identityToken from UserIdentity. Attempts to resolve the issue 1) I tried to make this database read a Convex mutation instead of a Convex query, but that put me down the path of putting a Convex mutation in a useEffect() before loading the form. This caused the issue of too many re-renderings. 2) Perhaps this is an issue about the loading of components, and this is an issue that the <Authenticated> component can solve, but I am stuck trying to use it. 3) Perhaps the customQuery and auth.ts approach in notesGPT can resolve the issue if it is indeed about the order of loading.
lee
lee10mo ago
i recommend putting the <Authenticated> around the component that calls useQuery like
export default function SettingsPage() {
return <Authenticated>
<AuthenticatedSettingsPage />
</Authenticated>;
}
function AuthenticatedSettingsPage() {
// copy the contents of your existing SettingsPage component
}
export default function SettingsPage() {
return <Authenticated>
<AuthenticatedSettingsPage />
</Authenticated>;
}
function AuthenticatedSettingsPage() {
// copy the contents of your existing SettingsPage component
}
Matt Luo
Matt LuoOP10mo ago
Well, sweet Texas Tea! That seems to be working. I am embarrassed. But, I had searched around for </Authenticated> and didn't get much Why did my multi-part query function need </Authenticated> but my simple queryAuthUserIdentity doesn't?
lee
lee10mo ago
queryAuthUserIdentity doesn't throw an error if it's authenticated (it returns null)
Matt Luo
Matt LuoOP10mo ago
But queryAuthUserIdentity seemed to be returning a value for me; that's how I was able to print the tokenIdentifier to the front end
lee
lee10mo ago
it returns null the first time, and then you authenticate and it rerenders with a value whereas getUserSettingsByTokenIdentifier throws an error, so the authentication and rerender never happen
Matt Luo
Matt LuoOP10mo ago
So is <Authenticated> component a critical component for a Next.js+Convex project? Now that I understand it better, I see it here: https://github.com/thomasballinger/convex-clerk-users-table/blob/a78a9083cede8b834a80e1c6c2d189ee08b490c9/src/main.tsx#L45 with this comment: {/* Authenticated is for having a JWT token from Clerk */} From this documentation section, https://docs.convex.dev/auth/clerk#logged-in-and-logged-out-views I did not infer that I had to explicitly say the user is authenticated. Seems like I am saying there is a Clerk user twice, once in ConvexProviderWithClerk and again with <Authenticated>
ballingt
ballingt10mo ago
ConvexProviderWithClerk is for allowing you to check for a Clerk user, Authenticated says "don't render these children until there is a clerk user and it has sent its token to Convex" which is important if you write queries that will error when run without auth
Matt Luo
Matt LuoOP10mo ago
I see, okay, I get it now. Thank you all!

Did you find this page helpful?