Open
[Bug]-OpenAPI 给已关闭 issue 添加标签:写入成功但返回反序列化错误(closed_by 类型不匹配) #2230
Wang HengAdd on  13 days ago
Wang Heng
13 days ago Create

遇到 bug 的页面

GitCode OpenAPI:创建 issue 标签接口

curl -sS -X POST "https://api.gitcode.com/api/v5/repos/{owner}/{repo}/issues/{number}/labels" \
  -H "Authorization: Bearer ${gitcode_token}" \
  -H "Content-Type: application/json" \
  -d '["test-label"]'

相关接口:

  • POST /api/v5/repos/{owner}/{repo}/issues/{number}/labels

遇到 bug 的功能模块

OpenAPI / Issue 标签 / 已关闭(closed)状态的 issue

问题描述

已关闭的 issue 调用「创建 issue 标签」接口时,标签实际写入成功,但响应返回的是一个服务端反序列化错误,error_message 里是一段 Java 异常文本;HTTP 状态码也从正常的 201 变成 200。对开启中的 issue 调用同一接口则一切正常:201 加标签数组。

差异完全由 issue 的 state 决定。我们在一次批量打标里连续调用了 101 次:84 个 closed issue 全部返回该错误,17 个 open issue 全部正常,没有一个例外。

错误信息本身指出了原因:

JSON parse error: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
 ... (through reference chain: com.gitcode.hubservice.feign.dto.issue.ProjectIssueSimpleRsp["closed_by"])

ProjectIssueSimpleRsp.closed_by 声明为 java.lang.String,但上游返回的是一个对象。只有 closed issue 才有非空的 closed_by,所以只有 closed issue 会踩到这一条。

实际影响是调用方无法用响应判断成败:按 error_code / error_message 判断,会把一次已经成功的写入误判为失败,进而重试或回滚;只有回读 issue 才能确认。HTTP 状态码 200 / 201 确实能区分这两种情况,但「200 表示失败、201 表示成功」既反直觉也没有文档依据,不适合作为判据。

重现步骤

  1. 在任意仓库新建一个 issue,并为该仓库创建一个标签(例如 test-label)。
  2. 关闭该 issue。
  3. 调用创建 issue 标签接口:
curl -sS -w "\nHTTP %{http_code}\n" -X POST \
  "https://api.gitcode.com/api/v5/repos/{owner}/{repo}/issues/{number}/labels" \
  -H "Authorization: Bearer ${gitcode_token}" \
  -H "Content-Type: application/json" \
  -d '["test-label"]'
  1. 观察响应:HTTP 200,body 为
error_code: 200
error_code_name: OK
error_message: >-
  Error while extracting response for type [class
  com.gitcode.hubservice.feign.dto.issue.ProjectIssueSimpleRsp] and content type
  [application/json]; nested exception is
  org.springframework.http.converter.HttpMessageNotReadableException: JSON parse
  error: Cannot deserialize value of type `java.lang.String` from Object value
  (token `JsonToken.START_OBJECT`); nested exception is
  com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
  deserialize value of type `java.lang.String` from Object value (token
  `JsonToken.START_OBJECT`) at [Source:
  (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column:
  1835] (through reference chain:
  com.gitcode.hubservice.feign.dto.issue.ProjectIssueSimpleRsp["closed_by"])
  1. 回读该 issue,labels 里能看到 test-label,说明写入其实成功了。
  2. 重新打开该 issue,或换一个 open 状态的 issue,重复第 3 步:HTTP 201,body 是正常的标签数组。

期望的行为

对 closed issue 调用该接口,行为与 open issue 一致:返回 201 和标签数组。

实际的行为

标签写入成功,但接口返回 200 加一段反序列化错误文本,调用方无法据此判断成败。

附加信息

  • 该接口是幂等的:对一个已经带有同名标签的 closed issue 重复 POST,同样稳定复现,因此复现时不需要真的改动数据。
  • 可能同源的另一处现象:GET /api/v5/repos/{owner}/{repo}/issues/{number} 返回的 closed_by 恒为 null,即使 issue 已关闭且有明确的关闭人。怀疑是同一个字段在 DTO 里的映射有问题。
likedislike
AtomGit小助手
AtomGit小助手Collaborators
12 days ago Comments:

您反馈的该问题确认是个bug ,需要等待修复,我们会尽快解决,待修复好之后再给您回复

likedislike
AtomGit小助手
AtomGit小助手Collaborators
9 days ago Comments:

您好,您反馈的该问题目前已修复,建议您重新尝试一下,如有疑问,可及时联系我们,感谢您的支持!

likedislike