From be7cde75395b179d1ada9d2c97ede0217076d1fe Mon Sep 17 00:00:00 2001 From: Zhaoqi Xu Date: Thu, 17 Sep 2026 20:25:43 +0800 Subject: [PATCH] fix(repo): surface unrelated histories on Sync Fork (#39258) Sync Fork already maps merge conflicts to a JSON error. Unrelated histories still went through `ServerError`, so the UI showed a 500 HTML snippet instead of the same user-facing message PR merge already uses (`repo.pulls.unrelated_histories`). The API path returned 500 for the same git error; PR merge returns 409. Match that. Fixes #36772 AI assistance was used to locate the handler gap and draft the mapping. I reviewed and take responsibility for the change. Signed-off-by: Zhaoqi Xu --- routers/api/v1/repo/branch.go | 5 +++++ routers/web/repo/branch.go | 3 +++ templates/swagger/v1-openapi3.generated.json | 3 +++ templates/swagger/v1-swagger.generated.json | 3 +++ 4 files changed, 14 insertions(+) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 758d1cd7f0e..38d5f5e1907 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -1331,6 +1331,8 @@ func MergeUpstream(ctx *context.APIContext) { // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/notFound" + // "409": + // "$ref": "#/responses/error" form := web.GetForm[*api.MergeUpstreamRequest](ctx) mergeStyle, err := repo_service.MergeUpstream(ctx, ctx.Doer, ctx.Repo.Repository, form.Branch, form.FfOnly) if err != nil { @@ -1343,6 +1345,9 @@ func MergeUpstream(ctx *context.APIContext) { } else if errors.Is(err, util.ErrPermissionDenied) { ctx.APIError(http.StatusForbidden, err.Error()) return + } else if pull_service.IsErrMergeConflicts(err) || pull_service.IsErrMergeUnrelatedHistories(err) { + ctx.APIError(http.StatusConflict, err.Error()) + return } ctx.APIErrorInternal(err) return diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index b3c7cc0eb67..e2edcc75d65 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -240,6 +240,9 @@ func MergeUpstream(ctx *context.Context) { } else if pull_service.IsErrMergeConflicts(err) { ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict")) return + } else if pull_service.IsErrMergeUnrelatedHistories(err) { + ctx.JSONError(ctx.Tr("repo.pulls.unrelated_histories")) + return } ctx.ServerError("MergeUpstream", err) return diff --git a/templates/swagger/v1-openapi3.generated.json b/templates/swagger/v1-openapi3.generated.json index 8da43734261..e9926c77acb 100644 --- a/templates/swagger/v1-openapi3.generated.json +++ b/templates/swagger/v1-openapi3.generated.json @@ -27155,6 +27155,9 @@ }, "404": { "$ref": "#/components/responses/notFound" + }, + "409": { + "$ref": "#/components/responses/error" } }, "summary": "Merge a branch from upstream", diff --git a/templates/swagger/v1-swagger.generated.json b/templates/swagger/v1-swagger.generated.json index a4f9c7ade98..bff62700924 100644 --- a/templates/swagger/v1-swagger.generated.json +++ b/templates/swagger/v1-swagger.generated.json @@ -14997,6 +14997,9 @@ }, "404": { "$ref": "#/responses/notFound" + }, + "409": { + "$ref": "#/responses/error" } } }