siyuan-note/siyuan · error

appearance files not found at

Error message

appearance files not found at [%s]

What it means

The SiYuan CLI kernel binary validates before running any subcommand (except workspace) that an appearance/langs directory exists under the resolved working directory. resolveWorkingDir() probes candidate directories relative to the executable (resources/, app/, macOS bundle Resources) and falls back to util.WorkingDir; if none of them contains appearance/langs, this error aborts the command. It protects UI/i18n-dependent operations from running against an incomplete or mis-deployed installation.

Solutions

  1. Install the kernel binary in the expected layout so its parent directory contains appearance/langs (production: resources/kernel/SiYuan-Kernel with resources/appearance/).
  2. Re-download/reinstall the full SiYuan package instead of just the kernel executable.
  3. Run the binary from a checkout that includes app/appearance/langs (resolveWorkingDir probes kernel/ → app/ and exeDir/app), e.g. build to kernel/ of the repo.
  4. Verify the path printed in the error actually lacks appearance/langs and create/copy that directory there if it is a custom deployment you control.

Example fix

// before: copying only the binary
cp SiYuan-Kernel /opt/siyuan/
// after: keep the resources layout
cp -r resources /opt/siyuan/   # contains kernel/SiYuan-Kernel and appearance/langs
Defensive patterns

Strategy: validation

Validate before calling

// Go: check appearance files before invoking the CLI binary
langsDir := filepath.Join(installDir, "appearance", "langs")
if fi, err := os.Stat(langsDir); err != nil || !fi.IsDir() {
    return fmt.Errorf("kernel install incomplete: %s missing", langsDir)
}

Try / catch

if err := runKernelCLI(args); err != nil && strings.Contains(err.Error(), "appearance files not found") {
    // repair installation or reinstall before retrying
}

Prevention

When it happens

Trigger: Running any rootCmd subcommand whose PersistentPreRunE executes (i.e. not under the workspace subcommand) when os.Stat(filepath.Join(util.WorkingDir, "appearance", "langs")) reports the directory does not exist — e.g. the kernel binary was copied out of its install tree, or a custom build of SiYuan-Kernel was placed in a bare directory.

Common situations: Downloading SiYuan-Kernel alone without the resources/appearance folder; moving the binary to /usr/local/bin or another isolated path; running a self-compiled kernel from kernel/ without the app/ layout; symlinked or containerized deployments that copy only the executable; macOS installs where the bundle Resources layout changed.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at kernel/cli/cmd/root.go:75

		sql.FlushQueue()
		return nil
	},
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		// workspace 子命令不需要工作空间校验
		if cmd.Parent() != nil && cmd.Parent().Name() == "workspace" {
			return nil
		}

		// 默认工作目录取内核可执行文件所在目录的上一级(打包后的 resources/,appearance/、stage/ 所在目录),
		// 而非内核可执行文件所在目录本身(resources/kernel/)。resolveWorkingDir() 会校验 appearance/langs 实际存在,
		// 兼容开发态等多种目录布局。
		if workingDir := resolveWorkingDir(); workingDir != "" {
			util.WorkingDir = workingDir
		}

		langsDir := filepath.Join(util.WorkingDir, "appearance", "langs")
		if _, err := os.Stat(langsDir); os.IsNotExist(err) {
			return fmt.Errorf("appearance files not found at [%s]", langsDir)
		}

		// 设置工作空间路径
		if workspacePath == "" {
			workspacePath = os.Getenv("SIYUAN_WORKSPACE_PATH")
		}
		if workspacePath == "" {
			workspacePath = filepath.Join(util.HomeDir, "SiYuan")
		}

		if _, err := os.Stat(workspacePath); os.IsNotExist(err) {
			return fmt.Errorf("directory not found: %s", workspacePath)
		}
		if !util.IsWorkspaceDir(workspacePath) {
			return fmt.Errorf("not a valid workspace: %s", workspacePath)
		}

		util.Mode = "prod"

View on GitHub (pinned to 9f775e8a12)