siyuan-note/siyuan · warning
-2
-2
Error message
Conf.Language(298) (localized: already used free trial)
What it means
StartFreeTrial calls the SiYuan cloud server to start a free subscription trial. When the cloud server responds with result code -2, it means this account has already consumed its free trial, so the kernel returns the localized message from Conf.Language(298) ("already used free trial"). This is an expected business rejection from the server, not a network or protocol failure.
Solutions
- Do not retry: the trial is permanently consumed for this account; show the localized message to the user and stop
- Purchase a subscription directly instead of using the trial (Settings - Account - Subscribe)
- If the user believes this is wrong (never actually trialed), contact SiYuan support / check which account is logged in
- Verify the intended account is logged in (Conf.GetUser()); a different account may still have an unused trial
Example fix
// before: blindly retrying on any error
if err := model.StartFreeTrial(); err != nil {
util.PushErrMsg(err.Error(), 7000)
retryTrial() // loops forever for used trials
}
// after: treat trial-used as terminal, surface message once
if err := model.StartFreeTrial(); err != nil {
util.PushErrMsg(err.Error(), 7000) // localized 'already used free trial'
// disable the trial button; guide user to purchase instead
disableTrialButton()
} Defensive patterns
Strategy: try-catch
Validate before calling
// track trial usage client-side before offering the button
if localStorage.getItem("siyuan-free-trial-used") === "true" { hideTrialButton(); } Try / catch
try {
await startFreeTrial();
} catch (e) {
if (e.message.includes(trialUsedMsg)) { disableTrialButton(); showSubscribeOption(); }
else { showError(e.message); }
} Prevention
- Never auto-retry StartFreeTrial on error
- Persist a local 'trial used' flag after first occurrence
- Guide users to the purchase flow instead of the trial when this error appears
When it happens
Trigger: Calling StartFreeTrial (exposed via the subscription/trial API endpoint) with an account that has previously activated the free trial. The HTTP status is 200 but the JSON body carries Code == -2.
Common situations: A user re-installing SiYuan or switching devices tries the free trial again with the same SiYuan account; testing the trial endpoint repeatedly in development; a shared/team account where another member already used the trial.
Related errors
- Conf.Language(298)
- Conf.Language(31)
- The sidebar feature that comes with the plugin needs to be…
- This feature requires the purchase of an <a target='_blank'…
- 0
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c66b8f11efbc641a.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/cloud_service.go:136
request := httpclient.NewCloudRequest30s()
resp, err := request.
SetSuccessResult(requestResult).
SetCookies(&http.Cookie{Name: "symphony", Value: user.UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/user/startFreeTrial")
if err != nil {
logging.LogErrorf("start free trial failed: %s", err)
return ErrFailedToConnectCloudServer
}
if http.StatusUnauthorized == resp.StatusCode {
invalidUser()
return errors.New(Conf.Language(31))
}
if http.StatusOK != resp.StatusCode {
logging.LogErrorf("start free trial failed: %d", resp.StatusCode)
return ErrFailedToConnectCloudServer
}
if -2 == requestResult.Code { // 已经试用订阅过
return errors.New(Conf.Language(298))
}
if 0 != requestResult.Code {
return errors.New(requestResult.Msg)
}
return
}
func DeactivateUser() (err error) {
release := lockAssetSourceChange()
defer release()
if Conf.Sync.Provider == conf.ProviderSiYuan {
if err = requireCompleteAssetDownloads(); err != nil {
return
}
}
user := Conf.GetUser()
if user == nil {
return errors.New(Conf.Language(31))View on GitHub (pinned to 9f775e8a12)