siyuan-note/siyuan · error

write box conf [%s] failed: %w

Error message

write box conf [%s] failed: %w

What it means

In saveConf0, after the directory is created, filelock.WriteFile(confPath, data) writes conf.json; on failure it calls util.ReportFileSysFatalError(err) (which escalates fatal FS conditions kernel-wide) and returns fmt.Errorf('write box conf [%s] failed: %w', confPath, err). This is the actual disk write of the notebook configuration.

Source

Thrown at kernel/model/box.go:329

func syncBoxConfCryptoBackup(boxID string, boxConf *conf.BoxConf) error {
	if !boxConf.Encrypted || boxConf.BoxCrypt == nil {
		return nil
	}
	if needWriteNotebookCryptBackup(boxID, boxConf.BoxCrypt) {
		return writeNotebookCryptBackup(boxID, boxConf.BoxCrypt)
	}
	return nil
}

func (box *Box) saveConf0(data []byte) error {
	confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
	if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, ".siyuan"), 0755); err != nil {
		return fmt.Errorf("mkdir box conf dir failed: %w", err)
	}
	if err := filelock.WriteFile(confPath, data); err != nil {
		util.ReportFileSysFatalError(err)
		return fmt.Errorf("write box conf [%s] failed: %w", confPath, err)
	}
	invalidateEncryptedPublishAccessCache()
	return nil
}

// validateBoxPath 校验 box 内相对路径,拒绝 .. 和绝对路径,确保最终路径在 <DataDir>/<boxID>/ 内。
func (box *Box) validateBoxPath(p string) (string, error) {
	return filesys.ValidateBoxRelativePath(box.ID, p)
}

func (box *Box) Ls(p string) (ret []*FileInfo, totals int, err error) {
	if _, err = box.validateBoxPath(p); err != nil {
		return
	}
	boxLocalPath := filepath.Join(util.DataDir, box.ID)
	if before, ok := strings.CutSuffix(p, ".sy"); ok {
		dir := before
		absDir := filepath.Join(boxLocalPath, dir)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Free space on / remount the data volume and retry the save.
  2. Close other SiYuan instances sharing the workspace (filelock serializes within one instance, not across sync tools).
  3. On Windows, exclude the workspace from AV/on-demand backup that may lock the file.
  4. If ReportFileSysFatalError fired, follow the kernel's fatal-FS handling — the workspace is likely unavailable and the kernel may need a restart.
Defensive patterns

Strategy: try-catch

Validate before calling

// Check free space / writability before a configuration save.
if err := filelock.WriteFile(filepath.Join(util.DataDir, ".writeprobe"), []byte{0}); err != nil {
    return fmt.Errorf("data dir not writable: %w", err)
}

Try / catch

// Fatal FS errors are escalated by ReportFileSysFatalError; surface them prominently.
if err := box.SaveConf(conf); err != nil && strings.Contains(err.Error(), "write box conf") {
    showFatalDiskError(errors.Unwrap(err))
}

Prevention

When it happens

Trigger: Any Box.SaveConf where the write to <DataDir>/<boxID>/.siyuan/conf.json fails: disk full mid-write, the volume unmounted under the kernel, a file-lock/permission failure, or the directory removed by another process between mkdir and write.

Common situations: USB/network drive holding the workspace dropped out; ENOSPC during a large session; antivirus/backup software locking conf.json on Windows; another SiYuan instance (or a sync tool) holds/removes the file.

Related errors


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