gwilliamnn
gwilliamnn2y ago

Bug after change function

I made a change on my schema, the table before called profile now is called profiles, I change all names on my code, is reflecting on the backend panel at the convex dashboard, but I'm getting this error:
- error Error: Could not find public function for 'profile:update'. Did you forget to run `npx convex dev` or `npx convex deploy`?

at ConvexHttpClient.mutation (webpack-internal:///(rsc)/./node_modules/.pnpm/convex@1.0.2_@clerk+clerk-react@4.23.1_react-dom@18.2.0_react@18.2.0/node_modules/convex/dist/esm/browser/http_client.js:126:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async handleClerkWebhook (webpack-internal:///(rsc)/./src/app/(api)/api/webhook/auth/utils.ts:35:17)
at async eval (webpack-internal:///(rsc)/./node_modules/.pnpm/next@13.4.12_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/future/route-modules/app-route/module.js:253:37)
- error Error: Could not find public function for 'profile:update'. Did you forget to run `npx convex dev` or `npx convex deploy`?

at ConvexHttpClient.mutation (webpack-internal:///(rsc)/./node_modules/.pnpm/convex@1.0.2_@clerk+clerk-react@4.23.1_react-dom@18.2.0_react@18.2.0/node_modules/convex/dist/esm/browser/http_client.js:126:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async handleClerkWebhook (webpack-internal:///(rsc)/./src/app/(api)/api/webhook/auth/utils.ts:35:17)
at async eval (webpack-internal:///(rsc)/./node_modules/.pnpm/next@13.4.12_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/future/route-modules/app-route/module.js:253:37)
And I call this function here:
if (body.type === "user.updated") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

console.log(name)

await client.mutation(api.profiles.update, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile updated")
}
if (body.type === "user.updated") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

console.log(name)

await client.mutation(api.profiles.update, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile updated")
}
12 Replies
ballingt
ballingt2y ago
Functions aren't given names based on tables, they're named based on the filename where they are exported. So what matters here is the name of the file where you wrote update function. What is that filename?
gwilliamnn
gwilliamnnOP2y ago
profiles.ts
gwilliamnn
gwilliamnnOP2y ago
No description
gwilliamnn
gwilliamnnOP2y ago
i think this is kinda a cache...
ballingt
ballingt2y ago
How are you running npx convex dev, is that showing an error?
gwilliamnn
gwilliamnnOP2y ago
no, the dev is working fine, the error happens when I make a query for update the profile
ballingt
ballingt2y ago
Could you share the code for that function, and the full file path of profiles.ts?
gwilliamnn
gwilliamnnOP2y ago
No description
gwilliamnn
gwilliamnnOP2y ago
yes just sec
gwilliamnn
gwilliamnnOP2y ago
No description
gwilliamnn
gwilliamnnOP2y ago
route.ts
import { NextResponse } from "next/server"
import type { WebhookEvent } from "@clerk/clerk-sdk-node"
import { ConvexHttpClient } from "convex/browser"
import { api } from "@convex/_generated/api"

const client = new ConvexHttpClient(process.env.CONVEX_URL!)

export async function POST(req: Request) {
const body = (await req.json()) as WebhookEvent
console.log(body)
try {
if (body.type === "user.created") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

const user = await client.query(api.profiles.getByUserId, { userId: body.data.id })
if (!user) {
await client.mutation(api.profiles.create, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile created")
}
}

if (body.type === "user.updated") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

console.log(name)

await client.mutation(api.profiles.update, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile updated")
}

if (body.type === "user.deleted") {
const user = await client.query(api.profiles.getByUserId, {
userId: body.data.id as string,
})
if (user) {
await client.mutation(api.profiles.remove, { userId: body.data.id as string })
} else {
console.log("Profile deleted not found profiles")
}
}

if (body.type === "session.created") {
// Check if session user_id already has a profiles, if not create one
const user = await client.query(api.profiles.getByUserId, {
userId: body.data.user_id,
})

console.log(user)
if (!user) {
console.log("data", body.data, "\n body.object", body.object)
console.log("Profile not found")
}
}

return NextResponse.json({ status: "ok" })
} catch (e) {
console.log(e)
return NextResponse.json({ status: "error" })
}
}
import { NextResponse } from "next/server"
import type { WebhookEvent } from "@clerk/clerk-sdk-node"
import { ConvexHttpClient } from "convex/browser"
import { api } from "@convex/_generated/api"

const client = new ConvexHttpClient(process.env.CONVEX_URL!)

export async function POST(req: Request) {
const body = (await req.json()) as WebhookEvent
console.log(body)
try {
if (body.type === "user.created") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

const user = await client.query(api.profiles.getByUserId, { userId: body.data.id })
if (!user) {
await client.mutation(api.profiles.create, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile created")
}
}

if (body.type === "user.updated") {
const name =
(body.data.first_name ? body.data.first_name : "No") +
" " +
(body.data.last_name ? body.data.last_name : "Name")

console.log(name)

await client.mutation(api.profiles.update, {
userId: body.data.id,
name,
email: body.data.email_addresses[0].email_address,
avatarUrl: body.data.profile_image_url,
})

console.log("Profile updated")
}

if (body.type === "user.deleted") {
const user = await client.query(api.profiles.getByUserId, {
userId: body.data.id as string,
})
if (user) {
await client.mutation(api.profiles.remove, { userId: body.data.id as string })
} else {
console.log("Profile deleted not found profiles")
}
}

if (body.type === "session.created") {
// Check if session user_id already has a profiles, if not create one
const user = await client.query(api.profiles.getByUserId, {
userId: body.data.user_id,
})

console.log(user)
if (!user) {
console.log("data", body.data, "\n body.object", body.object)
console.log("Profile not found")
}
}

return NextResponse.json({ status: "ok" })
} catch (e) {
console.log(e)
return NextResponse.json({ status: "error" })
}
}
profiles.ts
import { query, mutation } from "./_generated/server"
import { v } from "convex/values"

export const getAll = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("profiles").collect()
},
})

export const getByUserId = query({
args: {
userId: v.string(),
},
handler: async (ctx, { userId }) => {
return await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()
},
})

export const create = mutation({
args: {
userId: v.string(),
name: v.string(),
email: v.string(),
avatarUrl: v.optional(v.string()),
},
handler: async (ctx, { userId, name, email, avatarUrl }) => {
return await ctx.db.insert("profiles", {
userId,
name,
email,
avatarUrl,
})
},
})

export const update = mutation({
args: {
userId: v.string(),
name: v.string(),
email: v.string(),
avatarUrl: v.optional(v.string()),
},
handler: async (ctx, { userId, name, email, avatarUrl }) => {
const profiles = await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()

if (!profiles) {
return await ctx.db.insert("profiles", {
userId,
name,
email,
avatarUrl,
})
}

return await ctx.db.patch(profiles._id, {
userId,
name,
email,
avatarUrl,
})
},
})

export const remove = mutation({
args: {
userId: v.string(),
},
handler: async (ctx, { userId }) => {
const profiles = await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()

if (!profiles) {
return
}

return await ctx.db.delete(profiles._id)
},
})
import { query, mutation } from "./_generated/server"
import { v } from "convex/values"

export const getAll = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("profiles").collect()
},
})

export const getByUserId = query({
args: {
userId: v.string(),
},
handler: async (ctx, { userId }) => {
return await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()
},
})

export const create = mutation({
args: {
userId: v.string(),
name: v.string(),
email: v.string(),
avatarUrl: v.optional(v.string()),
},
handler: async (ctx, { userId, name, email, avatarUrl }) => {
return await ctx.db.insert("profiles", {
userId,
name,
email,
avatarUrl,
})
},
})

export const update = mutation({
args: {
userId: v.string(),
name: v.string(),
email: v.string(),
avatarUrl: v.optional(v.string()),
},
handler: async (ctx, { userId, name, email, avatarUrl }) => {
const profiles = await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()

if (!profiles) {
return await ctx.db.insert("profiles", {
userId,
name,
email,
avatarUrl,
})
}

return await ctx.db.patch(profiles._id, {
userId,
name,
email,
avatarUrl,
})
},
})

export const remove = mutation({
args: {
userId: v.string(),
},
handler: async (ctx, { userId }) => {
const profiles = await ctx.db
.query("profiles")
.withIndex("byUserId", (q) => q.eq("userId", userId))
.first()

if (!profiles) {
return
}

return await ctx.db.delete(profiles._id)
},
})
SORRY! :=) FOUND THE ERROR.. Sorrry ... miss file, I had 2 routes for webhook, WORK SMOOTH NOW
ballingt
ballingt2y ago
No problem, it's good to hear where mistakes often happen. Glad it's working!

Did you find this page helpful?