siyuan-note/siyuan · error
Backup failed
Error message
Backup failed: %s
What it means
This is the generic failure branch of UploadCloudSnapshot: after UploadTagIndex fails with any error that is not ErrCloudBackupCountExceeded, the kernel calls handleCloudError (which may surface account/network diagnostics), then wraps the cause with formatRepoErrorMsg into the localized 'Backup failed: %s' template (Language 84). The %s payload is a humanized repo error, so this message is an envelope whose real cause is embedded in the suffix.
Solutions
- Read the %s suffix in the error to identify the underlying repo error and fix that cause first
- Verify the cloud account is logged in (Settings - Account) and the subscription is active; re-login to refresh the token
- Check network connectivity/proxy settings and retry, since uploads resume incrementally
- Inspect kernel logs for the handleCloudError diagnostics (e.g. 401/403/5xx details) for the precise failure
- If the error persists for one snapshot, create a fresh snapshot tag and upload that instead
Example fix
// before
if err != nil {
return fmt.Errorf("backup failed")
}
// after
if err != nil {
if errors.Is(err, dejavu.ErrCloudBackupCountExceeded) {
return fmt.Errorf(Conf.Language(84), Conf.Language(154))
}
handleCloudError(err)
return fmt.Errorf(Conf.Language(84), formatRepoErrorMsg(err))
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check reachability and login before a long upload
const me = await fetchPost('/api/account/info', {});
if (!me.data || me.code !== 0) throw new Error('Not logged in to SiYuan Cloud'); Try / catch
try {
await fetchPost('/api/repo/uploadCloudSnapshot', {tag, id});
} catch (e) {
// parse the '%s' suffix of 'Backup failed: %s' for the repo error cause
console.error('cloud backup cause:', e.msg);
if (isTransient(e)) await sleep(retryBackoff); // retry network failures only
} Prevention
- Ensure a stable connection and valid cloud session before large uploads
- Re-login after password changes so the cloud token stays fresh
- Monitor kernel logs for handleCloudError diagnostics (HTTP status codes)
- Create a fresh snapshot tag and retry when one snapshot's index is corrupt
When it happens
Trigger: UploadTagIndex inside UploadCloudSnapshot fails for reasons other than the 12-snapshot quota: network failure mid-upload, cloud authentication failure (invalid/changed token), corrupted local index, or cloud-side 5xx responses.
Common situations: Uploading a large snapshot over an unstable connection; SiYuan Cloud session token expired after password change; cloud service maintenance returning HTTP errors; local repo key mismatch after restoring config from another machine.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Backup failed: The cloud can only support backup up to 12…
- Conf.Language(30) + " " + err.Error()
- Failed to obtain cloud info
- bazaar package information has not synced yet
- Conf.Language(123)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/38d0103849bd130c.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/repository.go:1549
return
}
case conf.ProviderWebDAV, conf.ProviderS3, conf.ProviderLocal:
if !IsPaidUser() {
util.PushErrMsg(Conf.Language(214), 5000)
return
}
}
util.PushEndlessProgress(Conf.Language(116))
defer util.PushClearProgress()
uploadFileCount, uploadChunkCount, uploadBytes, err := repo.UploadTagIndex(tag, id, map[string]any{eventbus.CtxPushMsg: eventbus.CtxPushMsgToStatusBarAndProgress})
if err != nil {
if errors.Is(err, dejavu.ErrCloudBackupCountExceeded) {
err = fmt.Errorf(Conf.Language(84), Conf.Language(154))
return
}
handleCloudError(err)
err = fmt.Errorf(Conf.Language(84), formatRepoErrorMsg(err))
return
}
msg := fmt.Sprintf(Conf.Language(152), uploadFileCount, uploadChunkCount, humanize.BytesCustomCeil(uint64(uploadBytes), 2))
util.PushMsg(msg, 5000)
util.PushStatusBar(msg)
return
}
func RemoveCloudRepoTag(tag string) (err error) {
assetDownloadSourceMu.RLock()
defer assetDownloadSourceMu.RUnlock()
if 1 > len(Conf.Repo.Key) {
err = errors.New(Conf.Language(26))
return
}
handleCloudError := cloudRepoErrorHandler()
defer func() { handleCloudError(err) }()View on GitHub (pinned to 9f775e8a12)