Skip to content

Commit f2bb9d2

Browse files
sweetmantechclaude
andauthored
fix: create room if roomId is provided but doesn't exist (#136)
When a roomId is provided to setupConversation but the room doesn't actually exist in the database, we now check and create it instead of failing with a foreign key constraint error on the memories table. This fixes the error: Error creating memory: Key (room_id)=(...) is not present in table "rooms" Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b52bedb commit f2bb9d2

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

lib/chat/__tests__/setupConversation.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,22 @@ vi.mock("@/lib/messages/filterMessageContentForMemories", () => ({
2121
default: vi.fn((msg: unknown) => msg),
2222
}));
2323

24+
vi.mock("@/lib/supabase/rooms/selectRoom", () => ({
25+
default: vi.fn(),
26+
}));
27+
2428
import { generateUUID } from "@/lib/uuid/generateUUID";
2529
import { createNewRoom } from "@/lib/chat/createNewRoom";
2630
import insertMemories from "@/lib/supabase/memories/insertMemories";
2731
import filterMessageContentForMemories from "@/lib/messages/filterMessageContentForMemories";
32+
import selectRoom from "@/lib/supabase/rooms/selectRoom";
2833
import { setupConversation } from "../setupConversation";
2934

3035
const mockGenerateUUID = vi.mocked(generateUUID);
3136
const mockCreateNewRoom = vi.mocked(createNewRoom);
3237
const mockInsertMemories = vi.mocked(insertMemories);
3338
const mockFilterMessageContentForMemories = vi.mocked(filterMessageContentForMemories);
39+
const mockSelectRoom = vi.mocked(selectRoom);
3440

3541
/**
3642
* Helper to create a UIMessage for testing.
@@ -53,6 +59,8 @@ describe("setupConversation", () => {
5359
mockGenerateUUID.mockReturnValue("generated-uuid");
5460
mockCreateNewRoom.mockResolvedValue(undefined);
5561
mockInsertMemories.mockResolvedValue(null);
62+
// By default, selectRoom returns an existing room when roomId is provided
63+
mockSelectRoom.mockResolvedValue({ id: "existing-room-id" } as never);
5664
});
5765

5866
describe("room creation", () => {
@@ -72,7 +80,8 @@ describe("setupConversation", () => {
7280
});
7381
});
7482

75-
it("does NOT create a room when roomId is provided", async () => {
83+
it("does NOT create a room when roomId is provided and room exists", async () => {
84+
mockSelectRoom.mockResolvedValue({ id: "existing-room-id" } as never);
7685
const promptMessage = createUIMessage("Hello");
7786

7887
await setupConversation({
@@ -81,9 +90,29 @@ describe("setupConversation", () => {
8190
promptMessage,
8291
});
8392

93+
expect(mockSelectRoom).toHaveBeenCalledWith("existing-room-id");
8494
expect(mockCreateNewRoom).not.toHaveBeenCalled();
8595
});
8696

97+
it("creates a room when roomId is provided but room does NOT exist", async () => {
98+
mockSelectRoom.mockResolvedValue(null);
99+
const promptMessage = createUIMessage("Hello");
100+
101+
await setupConversation({
102+
accountId: "account-123",
103+
roomId: "non-existent-room-id",
104+
promptMessage,
105+
});
106+
107+
expect(mockSelectRoom).toHaveBeenCalledWith("non-existent-room-id");
108+
expect(mockCreateNewRoom).toHaveBeenCalledWith({
109+
accountId: "account-123",
110+
roomId: "non-existent-room-id",
111+
artistId: undefined,
112+
lastMessage: promptMessage,
113+
});
114+
});
115+
87116
it("passes artistId to createNewRoom when provided", async () => {
88117
const promptMessage = createUIMessage("Hello");
89118

lib/chat/setupConversation.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { UIMessage } from "ai";
22
import { generateUUID } from "@/lib/uuid/generateUUID";
33
import { createNewRoom } from "@/lib/chat/createNewRoom";
44
import insertMemories from "@/lib/supabase/memories/insertMemories";
5+
import selectRoom from "@/lib/supabase/rooms/selectRoom";
56
import filterMessageContentForMemories from "@/lib/messages/filterMessageContentForMemories";
67

78
interface SetupConversationParams {
@@ -44,8 +45,18 @@ export async function setupConversation({
4445
const finalRoomId = roomId || generateUUID();
4546
const finalMemoryId = memoryId || generateUUID();
4647

47-
// Create room if roomId was not provided
48-
if (!roomId) {
48+
// Create room if needed:
49+
// - If no roomId was provided, create a new room
50+
// - If roomId was provided but doesn't exist, create it (prevents FK constraint errors)
51+
let shouldCreateRoom = !roomId;
52+
if (roomId) {
53+
const existingRoom = await selectRoom(roomId);
54+
if (!existingRoom) {
55+
shouldCreateRoom = true;
56+
}
57+
}
58+
59+
if (shouldCreateRoom) {
4960
await createNewRoom({
5061
accountId,
5162
roomId: finalRoomId,

0 commit comments

Comments
 (0)