siyuan-note/siyuan · error

ErrPandocNotFound

ErrPandocNotFound

Error message

not found executable pandoc

What it means

ErrPandocNotFound is the sentinel error returned when a pandoc-backed conversion is requested but no usable pandoc executable is available. GetPandocRuntime() resolves pandoc's path (pandocBinPath); if it is empty (pandoc not installed or not found on PATH / in the install dir) or the kernel is not running in the standard container mode expected for the bundled pandoc, ConvertPandoc, Pandoc, and runClipboardMathPandoc return this error instead of shelling out.

Solutions

  1. Install pandoc (https://pandoc.org/installing.html or your package manager) and ensure it is on the PATH of the process running the kernel.
  2. Restart SiYuan after installing so GetPandocRuntime() re-detects the binary.
  3. If running in Docker, use the full image that bundles pandoc or add pandoc to your image build.
  4. Verify with `pandoc --version` under the same user/environment as the kernel (e.g. `sudo -u siyuan pandoc --version` for services).

Example fix

// before
// Dockerfile: FROM siyuan/siyuan:base-slim // no pandoc
// after
// Dockerfile:
// FROM siyuan/siyuan:base-slim
// RUN apt-get update && apt-get install -y pandoc && rm -rf /var/lib/apt/lists/*
Defensive patterns

Strategy: fallback

Validate before calling

binPath := util.GetPandocRuntime().BinPath
if binPath == "" || util.ContainerStd != util.Container {
    return util.ErrPandocNotFound // degrade gracefully, e.g. skip math conversion
}

Type guard

func pandocAvailable() bool {
    return util.GetPandocRuntime().BinPath != "" && util.ContainerStd == util.Container
}

Try / catch

out, err := util.Pandoc(from, to, o, content)
if errors.Is(err, util.ErrPandocNotFound) {
    logging.LogWarnf("pandoc unavailable, falling back to raw markdown export")
    return exportRawMarkdown(content, o)
}

Prevention

When it happens

Trigger: Calling kernel/util Pandoc(), ConvertPandoc(), runClipboardMathPandoc(), or the API route in kernel/api/lute_clipboard_math.go (clipboard math conversion) when GetPandocRuntime().BinPath is "" or Container != ContainerStd.

Common situations: pandoc not installed on a self-hosted desktop/server install; pandoc not on PATH for the user running the SiYuan kernel; running inside Docker with a slim image lacking pandoc; PATH differences between the service manager (systemd) and the interactive shell.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/db0b74b984c9fde6. Report an issue: GitHub.

Appendix: 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 8641553a1f)