Dokploy/dokploy · error · TRPCError

FORBIDDEN

FORBIDDEN

Error message

Access denied

What it means

Guard inside updateSlackNotification: the UPDATE on the notifications row for input.notificationId returned no row — meaning no notification with that ID exists (or it was deleted), so the update is rejected and the subsequent slack-table update never runs.

Source

Thrown at apps/dokploy/server/api/routers/ai.ts:247

		.input(
			z.object({
				aiId: z.string().min(1),
				logs: z.string().min(1),
				context: z.enum(["build", "runtime"]),
			}),
		)
		.mutation(async ({ input, ctx }) => {
			try {
				const aiSettings = await getAiSettingById(input.aiId);
				if (!aiSettings?.isEnabled) {
					throw new TRPCError({
						code: "BAD_REQUEST",
						message: "AI provider is not enabled",
					});
				}

				if (aiSettings.organizationId !== ctx.session.activeOrganizationId) {
					throw new TRPCError({
						code: "FORBIDDEN",
						message: "Access denied",
					});
				}

				const provider = selectAIProvider(aiSettings);
				const model = provider(aiSettings.model);

				const contextLabel =
					input.context === "build" ? "build/deployment" : "runtime/container";

				const result = await generateText({
					model,
					prompt: `You are a DevOps engineer analyzing ${contextLabel} logs. Analyze the following logs and provide:

1. **Summary**: A brief summary of what's happening
2. **Issues Found**: Any errors, warnings, or problems detected
3. **Root Cause**: The most likely root cause if there are errors

View on GitHub (pinned to 546686ea35)

Solutions

  1. Refetch the notification list and confirm the ID still exists before editing
  2. Handle BAD_REQUEST here as 'stale ID' and prompt the user to reload
  3. Verify you are passing notificationId (not the slack row ID) — they are different identifiers
Defensive patterns

Strategy: validation

Validate before calling

const dest = await db.query.notifications.findFirst({
  where: eq(notifications.notificationId, input.notificationId),
});
if (!dest) throw new Error('Notification no longer exists');

Try / catch

try { await updateSlackNotification(input); } catch (e) { if (e?.message?.includes('Error Updating')) { /* refetch list and retry */ } throw e; }

Prevention

When it happens

Trigger: Calling updateSlackNotification with a stale, deleted, or mistyped notificationId; concurrent deletion of the destination; updating a notification that belongs to a different resource scope.

Common situations: Client caching an old notification list; two admins editing where one deletes; ID copy/paste errors.

Understand the failure class

Related errors


AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27). Data as JSON: /api/errors/cad815574c312bac. Report an issue: GitHub.