diff --git a/artifacts/api-server/src/routes/notes.ts b/artifacts/api-server/src/routes/notes.ts index bca3ae8c..29ffe2d1 100644 --- a/artifacts/api-server/src/routes/notes.ts +++ b/artifacts/api-server/src/routes/notes.ts @@ -31,6 +31,15 @@ function parseIdParam(raw: unknown): { ok: true; id: number } | { ok: false; err return { ok: true, id: n }; } +// Postgres unique-constraint violation (SQLSTATE 23505). Used to distinguish +// duplicate-name errors (→ 409) from unrelated DB failures (→ 500). +function isUniqueViolation(e: unknown): boolean { + return ( + typeof e === "object" && e !== null && "code" in e && + (e as { code?: unknown }).code === "23505" + ); +} + function parseStringMax(v: unknown, max: number): string | undefined { if (v === undefined || v === null) return undefined; if (typeof v !== "string") return undefined; @@ -942,7 +951,11 @@ router.post("/note-folders", requireAuth, async (req, res): Promise => { .returning(); res.status(201).json({ ...folder, noteCount: 0 }); } catch (e) { - res.status(409).json({ error: "Folder already exists" }); + if (isUniqueViolation(e)) { + res.status(409).json({ error: "Folder already exists" }); + return; + } + throw e; } }); @@ -983,7 +996,11 @@ router.patch("/note-folders/:id", requireAuth, async (req, res): Promise = ); res.json({ ...folder, noteCount: Number(countRow?.count ?? 0) }); } catch (e) { - res.status(409).json({ error: "Folder already exists" }); + if (isUniqueViolation(e)) { + res.status(409).json({ error: "Folder already exists" }); + return; + } + throw e; } });