siyuan-note/siyuan · error · ErrPandocNotFound

ErrPandocNotFound

ErrPandocNotFound

Error message

not found executable pandoc

What it means

ErrPandocNotFound (kernel/util/pandoc.go:33) is returned by ConvertPandoc and Pandoc when GetPandocRuntime().BinPath is empty OR the kernel is not in ContainerStd mode (i.e. it is running in Docker or on mobile). InitPandoc only locates a binary on desktop builds; in other containers the runtime is intentionally left empty, so any pandoc-dependent conversion fails fast with this sentinel error.

Source

Thrown at kernel/util/pandoc.go:33

// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package util

import (
	"bytes"
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/88250/gulu"
	"github.com/siyuan-note/logging"
)

var ErrPandocNotFound = errors.New("not found executable pandoc")

func ConvertPandoc(dir string, args ...string) (path string, err error) {
	pandocBinPath := GetPandocRuntime().BinPath
	if "" == pandocBinPath || ContainerStd != Container {
		err = ErrPandocNotFound
		return
	}

	pandoc := exec.Command(pandocBinPath, args...)
	gulu.CmdAttr(pandoc)
	path = filepath.Join("temp", "convert", "pandoc", dir)
	absPath := filepath.Join(WorkspaceDir, path)
	if err = os.MkdirAll(absPath, 0755); err != nil {
		logging.LogErrorf("mkdir [%s] failed: [%s]", absPath, err)
		return
	}
	pandoc.Dir = absPath
	output, err := pandoc.CombinedOutput()

View on GitHub (pinned to 251596fc0d)

Solutions

  1. On desktop, set 设置 - 导出 - Pandoc 可执行文件路径 to a valid pandoc binary (validate with IsValidPandocBin).
  2. Install pandoc system-wide (e.g. apt install pandoc, brew install pandoc) and point SiYuan at it.
  3. On Docker/mobile, do not invoke pandoc-dependent import/export paths — fall back to plain Markdown.
  4. Verify the bundled pandoc binary exists at WorkingDir/pandoc/bin/pandoc on desktop.

Example fix

// before
path, err := util.ConvertPandoc(dir, args...)
if err != nil { return err }

// after (graceful degradation when pandoc is unavailable)
path, err := util.ConvertPandoc(dir, args...)
if errors.Is(err, util.ErrPandocNotFound) {
    logging.LogWarnf("pandoc unavailable, falling back to plain markdown: %s", err)
    return writePlainMarkdown(dir)
}
if err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check pandoc availability and container mode before calling Convert/Pandoc
if util.GetPandocRuntime().BinPath == "" || util.ContainerStd != util.Container {
    return util.ErrPandocNotFound // or fall back to plain markdown
}

Try / catch

path, err := util.ConvertPandoc(dir, args...)
if err != nil {
    if errors.Is(err, util.ErrPandocNotFound) {
        logging.LogWarnf("pandoc unavailable; falling back to plain export")
        return exportPlainMarkdown(dir)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ConvertPandoc/Pandoc when: (a) the desktop kernel booted without a bundled pandoc binary present and the user has not set a custom pandoc path, or (b) Container != ContainerStd (Docker image, Android, iOS, HarmonyOS gomobile builds).

Common situations: Fresh desktop install where the pandoc/ subdirectory was not shipped; user uninstalled/relocated pandoc; running the official Docker image (no pandoc bundled); mobile/harmony builds; the custom pandoc path set in settings points to a non-existent file (InitPandoc validates the version and falls back to empty).

Related errors


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