diff --git a/src/codegen/git/clients/git_repo_client.py b/src/codegen/git/clients/git_repo_client.py
index 0ac741077..c5d764985 100644
--- a/src/codegen/git/clients/git_repo_client.py
+++ b/src/codegen/git/clients/git_repo_client.py
@@ -218,6 +218,12 @@ def create_pull(
             logger.info(f"Repo {self.repo.name} is private. Disabling draft PRs.")
             draft = False
 
+        # First check if a PR already exists for this branch to avoid Sentry errors
+        existing_pr = self.get_pull_by_branch_and_state(head_branch_name=head_branch_name, base_branch_name=base_branch_name)
+        if existing_pr:
+            logger.info(f"Pull request for head branch: {head_branch_name} already exists at {existing_pr.html_url}. Skipping creation.")
+            return existing_pr
+
         try:
             pr = self.repo.create_pull(title=title or f"Draft PR for {head_branch_name}", body=body or "", head=head_branch_name, base=base_branch_name, draft=draft)
             logger.info(f"Created pull request for head branch: {head_branch_name} at {pr.html_url}")
diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py
index fc3e0557e..f36d70d68 100644
--- a/src/codegen/sdk/core/codebase.py
+++ b/src/codegen/sdk/core/codebase.py
@@ -998,13 +998,20 @@ def create_pr(self, title: str, body: str) -> PullRequest:
             raise ValueError(msg)
         self._op.stage_and_commit_all_changes(message=title)
         self._op.push_changes()
-        return self._op.remote_git_repo.create_pull(
+        # Use get_or_create_pull instead of create_pull to avoid errors when PR already exists
+        pr = self._op.remote_git_repo.get_or_create_pull(
             head_branch_name=self._op.git_cli.active_branch.name,
             base_branch_name=self._op.default_branch,
             title=title,
             body=body,
         )
 
+        if pr is None:
+            msg = f"Failed to create PR for branch {self._op.git_cli.active_branch.name}"
+            raise ValueError(msg)
+
+        return pr
+
     ####################################################################################################################
     # GRAPH VISUALIZATION
     ####################################################################################################################
diff --git a/tests/integration/codegen/git/codebase/test_codebase_create_pr.py b/tests/integration/codegen/git/codebase/test_codebase_create_pr.py
index 10f6b0943..4f3ef072d 100644
--- a/tests/integration/codegen/git/codebase/test_codebase_create_pr.py
+++ b/tests/integration/codegen/git/codebase/test_codebase_create_pr.py
@@ -36,3 +36,30 @@ def test_codebase_create_pr_active_branch_is_default_branch(codebase: Codebase):
     with pytest.raises(ValueError) as exc_info:
         codebase.create_pr(title="test-create-pr title", body="test-create-pr body")
     assert "Cannot make a PR from the default branch" in str(exc_info.value)
+
+
+def test_codebase_create_pr_existing_pr(codebase: Codebase):
+    # Create a branch and PR
+    head = f"test-create-pr-existing-{uuid.uuid4()}"
+    codebase.checkout(branch=head, create_if_missing=True)
+    file = codebase.files[0]
+    file.remove()
+    codebase.commit()
+
+    # Create the first PR
+    pr1 = codebase.create_pr(title="first PR title", body="first PR body")
+    assert pr1.title == "first PR title"
+    assert pr1.state == "open"
+
+    # Make another change and try to create another PR on the same branch
+    file = codebase.files[1] if len(codebase.files) > 1 else codebase.create_file("new_test_file.txt", "test content")
+    file.remove()
+    codebase.commit()
+
+    # This should return the existing PR instead of creating a new one
+    pr2 = codebase.create_pr(title="second PR title", body="second PR body")
+
+    # Verify it's the same PR
+    assert pr2.number == pr1.number
+    # The title should still be the original one since we're getting the existing PR
+    assert pr2.title == "first PR title"