From ff3224b35c456dc3ed66da61ddcceda11059260f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 29 Jul 2026 10:34:38 +0000 Subject: [PATCH] :bug: Normalize error response on duplicate file ID Capture unique constraint violation in insert-file! and return generic :not-found error instead of propagating raw PostgreSQL exception, preventing file existence oracle. AI-assisted-by: mimo-v2.5-pro --- backend/src/app/binfile/common.clj | 14 ++++++++--- backend/test/backend_tests/rpc_file_test.clj | 25 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/backend/src/app/binfile/common.clj b/backend/src/app/binfile/common.clj index a5b73564ea..f984a98550 100644 --- a/backend/src/app/binfile/common.clj +++ b/backend/src/app/binfile/common.clj @@ -748,9 +748,17 @@ (fmigr/upsert-migrations! conn file)) (let [file (encode-file cfg file)] - (db/insert! conn :file - (file->params file) - (assoc opts ::db/return-keys false)) + (try + (db/insert! conn :file + (file->params file) + (assoc opts ::db/return-keys false)) + (catch org.postgresql.util.PSQLException cause + (if (db/duplicate-key-error? cause) + (ex/raise :type :not-found + :code :object-not-found + :hint "file already exists" + :cause cause) + (throw cause)))) (->> (file->file-data-params file) (fdata/upsert! cfg)) diff --git a/backend/test/backend_tests/rpc_file_test.clj b/backend/test/backend_tests/rpc_file_test.clj index 1c07f35971..568855ca98 100644 --- a/backend/test/backend_tests/rpc_file_test.clj +++ b/backend/test/backend_tests/rpc_file_test.clj @@ -141,6 +141,31 @@ (let [result (:result out)] (t/is (= 0 (count result)))))))) +(t/deftest create-file-with-duplicate-id + (let [prof (th/create-profile* 1 {:is-active true}) + proj-id (:default-project-id prof) + file-id (uuid/next)] + + (t/testing "create file with specific id" + (let [data {::th/type :create-file + ::rpc/profile-id (:id prof) + :project-id proj-id + :id file-id + :name "first-file"} + out (th/command! data)] + (t/is (nil? (:error out))))) + + (t/testing "create file with duplicate id returns normalized error" + (let [data {::th/type :create-file + ::rpc/profile-id (:id prof) + :project-id proj-id + :id file-id + :name "duplicate-file"} + out (th/command! data) + err (:error out)] + (t/is (th/ex-info? err)) + (t/is (th/ex-of-type? err :not-found)))))) + (t/deftest file-gc-with-fragments (let [profile (th/create-profile* 1) file (th/create-file* 1 {:profile-id (:id profile)