siyuan-note/siyuan · error

formatRepoErrorMsg(err)

Error message

formatRepoErrorMsg(err)

What it means

CreateCloudSyncDir wraps a failure from repo.CreateCloudRepo(name) with formatRepoErrorMsg, which maps known repository errors (cloud auth failed, cloud object not found, cloud lock contention, decrypt failure, DNS/timeout, etc.) to localized user-facing messages before returning them. The error means the SiYuan cloud repository could not be created; the wrapped message identifies the underlying cause (authentication, network, quota/lock, or file-system problem). The kernel also runs cloudRepoErrorHandler, so the failure is additionally reported through the UI notification path.

Solutions

  1. Read the localized message: if it indicates login failure, re-authenticate (Settings - Account - log in again) and retry CreateCloudSyncDir.
  2. If it indicates the repo/object exists, choose a different cloud sync dir name or remove the existing one first via RemoveCloudSyncDir.
  3. If it is a network/DNS/timeout message, fix connectivity (DNS, proxy, firewall) and retry.
  4. If it indicates cloud lock, wait for the other device's sync to finish, then retry.
  5. If it indicates an unsupported/deprecated kernel version, upgrade SiYuan to the latest version.
  6. Check kernel logs for the 'unclassified repository error' line to identify the raw underlying error when no known family matched.

Example fix

// before: caller sees a generic cloud failure and retries blindly
err := model.CreateCloudSyncDir("main")
if err != nil { log.Println(err); return }

// after: authenticate and validate provider/name first, then handle mapped errors
if conf.ProviderSiYuan != model.Conf.Sync.Provider && conf.ProviderLocal != model.Conf.Sync.Provider {
    return errors.New("cloud sync requires the SiYuan or Local provider")
}
if !model.IsLoggedIn() { // refresh token first
    return errors.New("log in to SiYuan cloud before creating a sync dir")
}
if err := model.CreateCloudSyncDir(name); err != nil {
    util.PushErrMsg(err.Error(), 7000) // show mapped localized message to user
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// caller-side pre-check (frontend/JS)
const cfg = (await fetchPost("/api/sync/getSyncInfo", {})).data;
if (cfg.provider !== 2 && cfg.provider !== 4) throw new Error("provider must be SiYuan or Local");
if (!cfg.cloudUser) throw new Error("log in to SiYuan cloud first");
if (!/^[\w\u4e00-\u9fa5-]+$/.test(name)) throw new Error("invalid cloud dir name");

Try / catch

try {
  await fetchPost("/api/sync/createCloudSyncDir", {name});
} catch (e) {
  // message is already localized by formatRepoErrorMsg
  if (/login|auth/i.test(e.message)) openLoginDialog();
  else if (/exist|already/i.test(e.message)) suggestAlternativeName();
  else showMessage(e.message);
}

Prevention

When it happens

Trigger: Calling CreateCloudSyncDir (HTTP API /api/sync/createCloudSyncDirContract) when: the cloud account token is expired or invalid (ErrCloudAuthFailed); the target repo name already exists remotely (ErrCloudObjectNotFound / conflict); network/DNS to siyuan cloud is down; the cloud data is locked by another device; or the local/remote repo state is corrupt (ErrRepoFatal). Also when Sync.Provider is not SiYuan/Local the earlier Language(131) error fires instead, so this wrapper only triggers for supported providers.

Common situations: User logged out or subscription expired so the token is stale; creating a sync dir from a machine with broken DNS or behind a firewall/proxy; another device holds the cloud lock mid-sync; system clock drift triggering ErrSystemTimeIncorrect; running an outdated kernel version rejected as ErrDeprecatedVersion; duplicate repo name from retrying creation.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/c6ea9a595a5d2424. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/sync.go:774

		return
	}

	name = util.RemoveInvalid(name)
	if !cloud.IsValidCloudDirName(name) {
		return errors.New(Conf.Language(37))
	}

	handleCloudError := cloudRepoErrorHandler()
	defer func() { handleCloudError(err) }()
	repo, err := newCloudRepositoryWithAssetSourceLocked()
	if err != nil {
		return
	}

	err = repo.CreateCloudRepo(name)
	if err != nil {
		handleCloudError(err)
		err = errors.New(formatRepoErrorMsg(err))
		return
	}
	return
}

func RemoveCloudSyncDir(name string) (err error) {
	release := lockAssetSourceChange()
	defer release()
	if name == Conf.Sync.CloudName {
		if err = requireCompleteAssetDownloads(); err != nil {
			return
		}
	}
	switch Conf.Sync.Provider {
	case conf.ProviderSiYuan, conf.ProviderLocal:
		break
	default:
		err = errors.New(Conf.Language(131))

View on GitHub (pinned to 9f775e8a12)