{"record":{"id":"28844caa396abb0b","repo":"siyuan-note/siyuan","slug":"requestresult-msg-cloud-server-message","errorCode":null,"errorMessage":"requestResult.Msg (cloud server message)","messagePattern":"requestResult\\.Msg \\(cloud server message\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/cloud_service.go","lineNumber":83,"sourceCode":"\tresp, err := request.\n\t\tSetSuccessResult(requestResult).\n\t\tSetCookies(&http.Cookie{Name: \"symphony\", Value: user.UserToken}).\n\t\tSetBody(payload).\n\t\tPost(util.GetCloudServer() + \"/apis/siyuan/ai/chatGPT\")\n\tif err != nil {\n\t\tlogging.LogErrorf(\"chat gpt failed: %s\", err)\n\t\terr = ErrFailedToConnectCloudServer\n\t\treturn\n\t}\n\tif http.StatusUnauthorized == resp.StatusCode {\n\t\tinvalidUser()\n\t\treturn \"\", true, errors.New(Conf.Language(31))\n\t}\n\tif http.StatusOK != resp.StatusCode {\n\t\treturn \"\", true, ErrFailedToConnectCloudServer\n\t}\n\tif 0 != requestResult.Code {\n\t\terr = errors.New(requestResult.Msg)\n\t\tstop = true\n\t\treturn\n\t}\n\n\tdata := requestResult.Data.(map[string]any)\n\tchoices := data[\"choices\"].([]any)\n\tif 1 > len(choices) {\n\t\tstop = true\n\t\treturn\n\t}\n\tchoice := choices[0].(map[string]any)\n\tmessage := choice[\"message\"].(map[string]any)\n\tret = message[\"content\"].(string)\n\n\tif nil != choice[\"finish_reason\"] {\n\t\tfinishReason := choice[\"finish_reason\"].(string)\n\t\tif \"length\" == finishReason {\n\t\t\tstop = false","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/cloud_service.go#L65-L101","documentation":"When the cloud ChatGPT proxy returns HTTP 200 but the envelope's Code is non-zero, CloudChatGPT returns errors.New(requestResult.Msg) (kernel/model/cloud_service.go:83) and sets stop=true. requestResult.Msg is the cloud server's own human-readable message (quota exhausted, content policy, upstream AI error), passed through verbatim to the caller.","triggerScenarios":"Calling CloudChatGPT when the server-side request fails for business reasons: AI quota/subscription exhausted, cloud upstream error, or the account not entitled to the AI service — i.e. Status 200 with a non-zero result code.","commonSituations":"Free trial ended or paid quota consumed; cloud-side AI provider outage surfaced as a server message; regional restrictions; account flagged or rate-limited by the cloud service.","solutions":["Read the returned error text (it is the server's message) and show it to the user verbatim; stop indicates no fallback content should be used","Check subscription/quota status in Settings - Account if the message mentions limits or trials","Retry later if the message indicates a temporary upstream/server error","In code, treat any error from CloudChatGPT as terminal (stop=true) rather than retrying blindly"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"reply, stop, err := model.CloudChatGPT(msg, ctx)\nif err != nil {\n    if stop { ui.showServerError(err.Error()) return } // server message is user-facing\n}","preventionTips":["Surface the returned message verbatim — it is the cloud's user-facing explanation","Monitor subscription/quota before enabling AI features","Do not auto-retry when stop=true; the failure is terminal for the request"],"tags":["cloud","api","upstream-error"],"backgroundTag":"upstream-api-error","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}