siyuan-note/siyuan · error

Upload failed: %s

Error message

Upload failed: %s

What it means

Returned by UploadAssets2Cloud (assets.go:1348) when the cloud upload endpoint returns a non-zero business code in requestResult.Code. The message is the kernel i18n key 94 ("Upload failed: %s") formatted with requestResult.Msg — the server-side reason string. The HTTP status is not 401 (that is error 420) and the request did not fail at the transport layer (that yields ErrFailedToConnectCloudServer).

Source

Thrown at kernel/model/assets.go:1348

			SetSuccessResult(requestResult).
			SetFile("file[]", absAsset).
			SetCookies(&http.Cookie{Name: "symphony", Value: uploadToken}).
			SetHeader("meta-type", metaType).
			SetHeader("biz-type", bizType).
			Post(util.GetCloudServer() + "/apis/siyuan/upload?ver=" + util.Ver)
		if nil != reqErr {
			logging.LogErrorf("upload assets failed: %s", reqErr)
			return count, ErrFailedToConnectCloudServer
		}

		if 401 == resp.StatusCode {
			err = errors.New(Conf.Language(31))
			return
		}

		if 0 != requestResult.Code {
			logging.LogErrorf("upload assets failed: %s", requestResult.Msg)
			err = fmt.Errorf(Conf.Language(94), requestResult.Msg)
			return
		}

		absAsset = filepath.ToSlash(absAsset)
		relAsset := absAsset[strings.Index(absAsset, "assets/"):]
		completedUploadAssets = append(completedUploadAssets, relAsset)
		logging.LogInfof("uploaded asset [%s]", relAsset)
		count++
	}

	if !ignorePushMsg {
		util.PushClearMsg(msgId)
	}

	if 0 < len(completedUploadAssets) {
		logging.LogInfof("uploaded [%d] assets", len(completedUploadAssets))
	}
	return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Read requestResult.Msg (surfaced in the formatted error) — it is the authoritative server reason; address that specific cause first (shrink the file, change type, free quota).
  2. Confirm the file passes the client size gate (limitSize = 3 MB free / 10 MB subscriber) before relying on the cloud; the client gate only logs a warning and skips, so an oversized file can still reach the server via other code paths.
  3. Re-authenticate (error 420) only if the message indicates auth; otherwise retry after resolving the server-reported cause.

Example fix

// before: only the wrapped message reaches the caller
err = fmt.Errorf(Conf.Language(94), requestResult.Msg)

// after: keep the server code for diagnosability
err = fmt.Errorf("%s (code %d)", fmt.Sprintf(Conf.Language(94), requestResult.Msg), requestResult.Code)
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: enforce the client size gate the kernel uses (3 MB free / 10 MB subscriber).
const limit = window.siyuan.user?.siyuanSubscriptionStatus === 0 ? 10 : 3
for (const f of assets) {
  if (f.size > limit * 1024 * 1024) { showMessage(`${f.name} exceeds ${limit} MB`); return }
}

Try / catch

// Surface the server's reason string and the code for diagnosability.
try {
  await uploadAssets2Cloud(assets, 'upload-assets')
} catch (e) {
  // e.message is "Upload failed: <server Msg>"; show it verbatim, do not mask.
  showMessage(e.message)
}

Prevention

When it happens

Trigger: Posting a file to /apis/siyuan/upload whose size exceeds the server quota, whose MIME type is rejected, when the account is over its storage quota, when the cloud rejects the meta-type/biz-type combination, or when the server returns any application-level error code (requestResult.Code != 0) with a descriptive Msg.

Common situations: Non-subscriber uploading a file larger than 3 MB (limitSize guard is client-side at 3 MB / 10 MB, but the server re-validates); uploading to Liandi with an asset the server deems invalid; transient server-side maintenance returning an error code; subscription lapse shrinking the server-side quota.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/30d37f8e2ff70e8a. Report an issue: GitHub.