diff --git a/server/src/__tests__/companies-service.test.ts b/server/src/__tests__/companies-service.test.ts index e3aa0c7ae4..d834695484 100644 --- a/server/src/__tests__/companies-service.test.ts +++ b/server/src/__tests__/companies-service.test.ts @@ -869,4 +869,12 @@ describeEmbeddedPostgres("companyService", () => { details: { agentsPaused: 1, runsCancelled: 1 }, }); }); + + it("getById returns null (not a query error) for non-UUID refs", async () => { + const svc = companyService(db); + await expect(svc.getById("tumbly-haus-creative")).resolves.toBeNull(); + await expect(svc.getById("not-a-uuid")).resolves.toBeNull(); + await expect(svc.getById("")).resolves.toBeNull(); + }); + }); diff --git a/server/src/services/companies.ts b/server/src/services/companies.ts index c3d03ebfcd..2105650a1c 100644 --- a/server/src/services/companies.ts +++ b/server/src/services/companies.ts @@ -39,6 +39,8 @@ import { heartbeatService } from "./heartbeat.js"; import { logActivity } from "./activity-log.js"; import { builtInAgentService } from "./built-in-agents.js"; + +const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; export interface CompanyActivityActor { actorType: "user" | "agent" | "system" | "plugin"; actorId: string; @@ -259,6 +261,11 @@ export function companyService(db: Db) { }, getById: async (id: string) => { + // Non-UUID refs previously reached the uuid-typed query and threw a + // DrizzleQueryError ("invalid input syntax for type uuid"), surfacing + // as HTTP 500 from GET /api/companies/:companyId. Treat them as + // not-found so the route returns 404. + if (!UUID_RE.test(id)) return null; const row = await getCompanyQuery(db) .where(eq(companies.id, id)) .then((rows) => rows[0] ?? null);