siyuan-note/siyuan · warning

This operation is not supported in read-only mode

Error message

This operation is not supported in read-only mode

What it means

Thrown by EnsureOnboarding() via Conf.Language(34) which resolves to 'This operation is not supported in read-only mode'. The onboarding flow (creating notebooks/documents for new users) is blocked when the kernel is running in read-only mode or when Conf.Publish.Enable is true (publish mode). This is a hard guard preventing data mutation in restricted deployment modes.

Source

Thrown at kernel/model/onboarding.go:109

	onboarding := Conf.Onboarding
	if !onboarding.NewUser || onboarding.Dismissed {
		return cloneOnboarding(onboarding), false, nil
	}

	boxes, listErr := ListNotebooks()
	if listErr != nil {
		return cloneOnboarding(onboarding), false, listErr
	}
	documentExists := onboarding.NotebookID != "" && onboarding.DocumentID != "" && filelock.IsExist(filepath.Join(
		util.DataDir, onboarding.NotebookID, onboarding.DocumentID+".sy"))
	if reconcileOnboarding(onboarding, boxes, documentExists) {
		Conf.Save()
	}
	if !onboarding.NewUser || onboarding.State == conf.OnboardingCompleted {
		return cloneOnboarding(onboarding), false, nil
	}
	if util.ReadOnly || Conf.Publish.Enable {
		return cloneOnboarding(onboarding), false, errors.New(Conf.Language(34))
	}

	if onboarding.NotebookID == "" {
		if len(boxes) > 0 {
			if len(boxes) == 1 && boxes[0].Name == Conf.Language(342) {
				onboarding.NotebookID = boxes[0].ID
				onboarding.State = conf.OnboardingNotebookCreated
				Conf.Save()
			} else {
				onboarding.State = conf.OnboardingCompleted
				onboarding.NewUser = false
				Conf.Save()
				return cloneOnboarding(onboarding), false, nil
			}
		}

		if onboarding.NotebookID == "" {
			onboarding.NotebookID, err = CreateBox(Conf.Language(342))

View on GitHub (pinned to 251596fc0d)

Solutions

  1. If onboarding is needed, disable read-only mode (--readonly=false) and ensure Conf.Publish.Enable is false during the initial user setup.
  2. For publish-mode deployments, dismiss or complete onboarding before enabling publish, or set Conf.Onboarding.NewUser=false in the config.
  3. In the calling code, check util.ReadOnly and Conf.Publish.Enable before calling EnsureOnboarding() and skip silently or show a different message.

Example fix

// before
onboarding, created, err := model.EnsureOnboarding()

// after
if util.ReadOnly || model.Conf.Publish.Enable {
    // Skip onboarding in read-only/publish mode
    return
}
onboarding, created, err := model.EnsureOnboarding()
Defensive patterns

Strategy: validation

Validate before calling

if util.ReadOnly || Conf.Publish.Enable {
    // Skip onboarding; show a static message instead
    return nil, false, nil
}

Type guard

func canOnboard() bool {
    return !util.ReadOnly && !Conf.Publish.Enable
}

Prevention

When it happens

Trigger: Calling EnsureOnboarding() when util.ReadOnly is true or Conf.Publish.Enable is true, and onboarding.NewUser is true and not dismissed and state is not completed. The function returns early with the onboarding clone and this error instead of proceeding to create notebooks.

Common situations: The SiYuan kernel was launched with the --readonly flag for a deployment that only serves published content. The publish feature is enabled, making the instance read-only for viewers. A new user visits a publish-mode instance and the frontend triggers the onboarding check, which correctly refuses.

Related errors


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