Prince
Prince7mo ago

Dashboard crashing, webhooks not receiving requests, and logs not showing on new project

@nipunn moving here to avoid cluttering #general Event IDs: 417b3977e3774793bd7b334912920064 23087658685c40b599ac24e9e9a1173a I think this might be happening after I try to hit my /clerk-users-webhook HTTP handler. It returns a 502 error on the Clerk dashboard and when I return to convex to check the logs, everything crashes until I refresh. This is a brand new project, webhook code:
import { httpRouter } from "convex/server"
import { httpAction } from "./_generated/server"
import { internal } from "./_generated/api"
import type { WebhookEvent } from "@clerk/backend"
import { Webhook } from "svix"

function ensureEnvironmentVariable() {
const value = process.env.CLERK_WEBHOOK_SECRET
if (value === undefined) {
throw new Error(`missing environment variable CLERK_WEBHOOK_SECRET`)
}
return value
}

const webhookSecret = ensureEnvironmentVariable()

const handleClerkWebhook = httpAction(async (ctx, request) => {
const event = await validateRequest(request)
if (!event) {
return new Response("Error occured", {
status: 400,
})
}
switch (event.type) {
case "user.created": // intentional fallthrough
case "user.updated": {
const existingUser = await ctx.runQuery(internal.users.getUser, {
subject: event.data.id,
})
if (existingUser && event.type === "user.created") {
console.warn("Overwriting user", event.data.id, "with", event.data)
}
console.log("creating/updating user", event.data.id)
await ctx.runMutation(internal.users.updateOrCreateUser, {
clerkUser: event.data,
})
break
}
case "user.deleted": {
// Clerk docs say this is required, but the types say optional?
const id = event.data.id!
await ctx.runMutation(internal.users.deleteUser, { id })
break
}
default: {
console.log("ignored Clerk webhook event", event.type)
}
}
return new Response(null, {
status: 200,
})
})

const http = httpRouter()
http.route({
path: "/clerk-users-webhook",
method: "POST",
handler: handleClerkWebhook,
})

async function validateRequest(
req: Request
): Promise<WebhookEvent | undefined> {
const payloadString = await req.text()

const svixHeaders = {
"svix-id": req.headers.get("svix-id")!,
"svix-timestamp": req.headers.get("svix-timestamp")!,
"svix-signature": req.headers.get("svix-signature")!,
}
const wh = new Webhook(webhookSecret)
let evt: Event | null = null
try {
evt = wh.verify(payloadString, svixHeaders) as Event
} catch (_) {
console.log("error verifying request")
return
}

return evt as unknown as WebhookEvent
}

export default http
import { httpRouter } from "convex/server"
import { httpAction } from "./_generated/server"
import { internal } from "./_generated/api"
import type { WebhookEvent } from "@clerk/backend"
import { Webhook } from "svix"

function ensureEnvironmentVariable() {
const value = process.env.CLERK_WEBHOOK_SECRET
if (value === undefined) {
throw new Error(`missing environment variable CLERK_WEBHOOK_SECRET`)
}
return value
}

const webhookSecret = ensureEnvironmentVariable()

const handleClerkWebhook = httpAction(async (ctx, request) => {
const event = await validateRequest(request)
if (!event) {
return new Response("Error occured", {
status: 400,
})
}
switch (event.type) {
case "user.created": // intentional fallthrough
case "user.updated": {
const existingUser = await ctx.runQuery(internal.users.getUser, {
subject: event.data.id,
})
if (existingUser && event.type === "user.created") {
console.warn("Overwriting user", event.data.id, "with", event.data)
}
console.log("creating/updating user", event.data.id)
await ctx.runMutation(internal.users.updateOrCreateUser, {
clerkUser: event.data,
})
break
}
case "user.deleted": {
// Clerk docs say this is required, but the types say optional?
const id = event.data.id!
await ctx.runMutation(internal.users.deleteUser, { id })
break
}
default: {
console.log("ignored Clerk webhook event", event.type)
}
}
return new Response(null, {
status: 200,
})
})

const http = httpRouter()
http.route({
path: "/clerk-users-webhook",
method: "POST",
handler: handleClerkWebhook,
})

async function validateRequest(
req: Request
): Promise<WebhookEvent | undefined> {
const payloadString = await req.text()

const svixHeaders = {
"svix-id": req.headers.get("svix-id")!,
"svix-timestamp": req.headers.get("svix-timestamp")!,
"svix-signature": req.headers.get("svix-signature")!,
}
const wh = new Webhook(webhookSecret)
let evt: Event | null = null
try {
evt = wh.verify(payloadString, svixHeaders) as Event
} catch (_) {
console.log("error verifying request")
return
}

return evt as unknown as WebhookEvent
}

export default http
schema:
import { defineSchema, defineTable } from "convex/server"
import { v } from "convex/values"

export default defineSchema({
users: defineTable({
// this is UserJSON from @clerk/backend
clerkUser: v.any(),
admin: v.optional(v.boolean()),
}).index("by_clerk_id", ["clerkUser.id"]),
})
import { defineSchema, defineTable } from "convex/server"
import { v } from "convex/values"

export default defineSchema({
users: defineTable({
// this is UserJSON from @clerk/backend
clerkUser: v.any(),
admin: v.optional(v.boolean()),
}).index("by_clerk_id", ["clerkUser.id"]),
})
No description
2 Replies
Prince
PrinceOP7mo ago
thanks for taking a look resolved, temporary issue affecting new deployments. Thanks Convex team.
nipunn
nipunn7mo ago
yep! Thanks for the report! we appreciate it also good idea to avoid cluttering general heh. Next time I'll play along too

Did you find this page helpful?