{"record":{"id":"82e6b673e0fefb04","repo":"siyuan-note/siyuan","slug":"failed-to-obtain-cloud-info","errorCode":null,"errorMessage":"Failed to obtain cloud info","messagePattern":"Failed to obtain cloud info","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/repository.go","lineNumber":3350,"sourceCode":"type Backup struct {\n\tSize    int64  `json:\"size\"`\n\tHSize   string `json:\"hSize\"`\n\tUpdated string `json:\"updated\"`\n\tSaveDir string `json:\"saveDir\"` // 本地备份数据存放目录路径\n}\n\ntype Sync struct {\n\tSize      int64  `json:\"size\"`\n\tHSize     string `json:\"hSize\"`\n\tUpdated   string `json:\"updated\"`\n\tCloudName string `json:\"cloudName\"` // 云端同步数据存放目录名\n\tSaveDir   string `json:\"saveDir\"`   // 本地同步数据存放目录路径\n}\n\nfunc GetCloudSpace() (s *Sync, b *Backup, hSize, hAssetSize, hTotalSize, hExchangeSize, hTrafficUploadSize, hTrafficDownloadSize, hTrafficAPIGet, hTrafficAPIPut string, err error) {\n\tstat, err := getCloudSpace()\n\tif err != nil {\n\t\terr = errors.New(Conf.Language(30) + \" \" + err.Error())\n\t\treturn\n\t}\n\n\tsyncSize := stat.Sync.Size\n\tsyncUpdated := stat.Sync.Updated\n\ts = &Sync{\n\t\tSize:    syncSize,\n\t\tHSize:   \"-\",\n\t\tUpdated: syncUpdated,\n\t}\n\n\tbackupSize := stat.Backup.Size\n\tbackupUpdated := stat.Backup.Updated\n\tb = &Backup{\n\t\tSize:    backupSize,\n\t\tHSize:   \"-\",\n\t\tUpdated: backupUpdated,\n\t}","sourceCodeStart":3332,"sourceCodeEnd":3368,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/repository.go#L3332-L3368","documentation":"GetCloudSpace queries the user's cloud storage statistics (sync space, assets, backup sizes, traffic). If the underlying getCloudSpace call fails (network error, auth failure, provider error), the kernel wraps the cause as Conf.Language(30) + \" \" + err.Error() — localized as \"Failed to obtain cloud info\". The original provider error text is appended after the localized prefix.","triggerScenarios":"Opening the cloud storage/sync statistics UI or calling the cloudSpace API while the kernel cannot reach or authenticate to the configured cloud provider (S3/WebDAV/Local endpoint).","commonSituations":"S3/WebDAV credentials wrong or expired; endpoint unreachable (offline, DNS, firewall, TLS issues); bucket/container missing or permission denied; provider returning an unexpected response; using Local provider with a bad endpoint path.","solutions":["Read the full error text after the localized prefix — it contains the underlying cause (auth, DNS, TLS, etc.) and fix that","Verify cloud provider credentials and endpoint in Settings - Account & Sync (test connection)","Check network connectivity and TLS/SkipTLS settings for self-signed endpoints","For S3, confirm the bucket exists and the access key has List/Get permissions; for WebDAV, confirm the URL and account","Retry after transient network issues — getCloudSpace failures are often connectivity-related"],"exampleFix":"// handling the wrapped error in a client\nconst res = await fetch('/api/sync/getCloudSpace', {method:'POST'});\nconst j = await res.json();\nif (j.code !== 0) {\n  // j.msg = \"Failed to obtain cloud info <root cause>\"\n  if (/401|Unauthorized|AccessDenied/.test(j.msg)) reconfigureCredentials();\n  else if (/no such host|timeout|connection/.test(j.msg)) checkNetwork();\n}","handlingStrategy":"try-catch","validationCode":"// probe connectivity/auth before requesting cloud space\nconst res = await fetch('/api/sync/getCloudSpace', {method:'POST'});\nconst j = await res.json();\nif (j.code !== 0) console.warn('Cloud info unavailable:', j.msg); // msg includes root cause after the localized prefix","typeGuard":"function isCloudInfoError(msg) { return typeof msg === 'string' && msg.startsWith('Failed to obtain cloud info'); }","tryCatchPattern":"try {\n  const stat = await getCloudSpace();\n} catch (e) {\n  if (/Unauthorized|AccessDenied|401|403/.test(e.message)) reconfigureProviderCredentials();\n  else if (/timeout|no such host|connection refused/.test(e.message)) await retryWithBackoff(getCloudSpace, 3);\n  else throw e;\n}","preventionTips":["Parse the text after 'Failed to obtain cloud info' — it names the real underlying cause","Test the cloud provider connection in Settings before relying on cloud statistics","Keep provider credentials and endpoint settings current; rotate keys before expiry","Handle transient network failures with retries rather than surfacing immediately"],"tags":["network","cloud","sync","api"],"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"}