siyuan-note/siyuan · error

mkdir box conf dir failed

Error message

mkdir box conf dir failed: %w

What it means

saveConf0 creates the <DataDir>/<boxID>/.siyuan directory (0755) before writing conf.json. This error wraps os.MkdirAll failure — the OS refused to create the notebook config directory, typically due to filesystem permissions or the path being occupied by a non-directory file.

Solutions

  1. Check OS permissions on <workspace>/data/<boxID>/ and ensure the process user can create directories there
  2. Verify no file named .siyuan exists in the notebook folder — delete or rename it
  3. Free disk space / raise quota if the disk is full
  4. Remount the workspace volume read-write and retry the operation

Example fix

// shell check before retry
ls -la <workspace>/data/<boxID>/
rm .siyuan  # if it is a regular file
chmod u+w <workspace>/data/<boxID>
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: verify writability before the call
if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, ".siyuan"), 0755); err != nil {
    return fmt.Errorf("data dir not writable: %w", err)
}

Try / catch

if err := box.SaveConf(conf); err != nil {
    if strings.Contains(err.Error(), "mkdir box conf dir failed") {
        // check permissions / disk space, then retry
    }
}

Prevention

When it happens

Trigger: Calling Box.SaveConf when os.MkdirAll(<DataDir>/<boxID>/.siyuan, 0755) fails: parent dir read-only, disk full, a file named .siyuan already exists, or insufficient OS permissions.

Common situations: Workspace on a read-only mount or external drive removed; running SiYuan as a user without write access to the data folder; sync client or backup tool replaced the .siyuan directory with a file; disk quota exceeded.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/box.go:380

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 {
	if !ast.IsNodeIDPattern(box.ID) {
		return fmt.Errorf("invalid box ID [%s]", box.ID)
	}

	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
	}

View on GitHub (pinned to 9f775e8a12)