siyuan-note/siyuan · error
start command: %w
Error message
start command: %w
What it means
Returned when exec.Cmd.Start() cannot launch the configured command for a stdio MCP server. Start resolves the binary on PATH (if not absolute) and execs it; failure means the binary could not be found, is not executable, or the OS refused to create the process. The wrapped error (typically exec.ErrNotFound, EACCES, or ENOENT) is preserved.
Source
Thrown at kernel/mcp/client/mcp.go:475
}
return conf.ResolveSecretsVars(model.Conf.Secrets, model.Conf.Variables, value)
}, runtime.GOOS)
if err != nil {
return nil, nil, fmt.Errorf("environment: %w", err)
}
cmd.Env = cmdEnv
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, nil, fmt.Errorf("stdin pipe: %w", err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, nil, fmt.Errorf("stdout pipe: %w", err)
}
cmd.Stderr = io.Discard
if err := cmd.Start(); err != nil {
return nil, nil, fmt.Errorf("start command: %w", err)
}
connectCtx, connectCancel := context.WithTimeout(ctx, serverTimeout(server))
defer connectCancel()
transport := &mcp.IOTransport{Reader: stdout, Writer: stdin}
session, err := client.Connect(connectCtx, transport, nil)
if err != nil {
cmd.Process.Kill()
cmd.Wait()
return nil, cmd, fmt.Errorf("connect: %w", err)
}
return session, cmd, nil
}
type environmentEntry struct {
name string
value stringView on GitHub (pinned to 251596fc0d)
Solutions
- Verify the binary exists and is executable from the kernel's own environment: run exec.LookPath(server.Command) (or 'which <cmd>') using the same user/PATH the kernel runs under.
- Use an absolute path in server.Command to remove PATH ambiguity.
- Ensure the runtime (node, python, npx, uvx, etc.) is installed and on the PATH seen by the kernel process — for a systemd unit, set Environment=PATH=... explicitly.
- On Unix, chmod +x the binary; on Windows, include the extension (.exe, .cmd, .bat) if needed.
Example fix
// before
server.Command = "mcp-server"
server.Args = []string{}
// after
server.Command = "/usr/local/bin/mcp-server"
server.Args = []string{} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the command resolves on the kernel's PATH before attempting connect.
import "os/exec"
func commandResolves(cmd string) error {
if cmd == "" { return errors.New("empty command") }
if _, err := exec.LookPath(cmd); err != nil { return err }
return nil
} Try / catch
// Distinguish 'not found' from 'permission denied' for UI messaging.
var pathErr *exec.Error
if errors.As(err, &pathErr) {
// pathErr.Name is the command; surface 'install <runtime>' hint
} Prevention
- Prefer absolute paths in server.Command.
- For service deployments, set an explicit PATH in the unit environment.
- Run exec.LookPath at config-save time.
When it happens
Trigger: connectStdio calls cmd.Start() with server.Command that does not exist on PATH, is not marked executable (Unix), is a directory, or the kernel process lacks permission to fork/exec. Also fired when the command path is absolute but points at a missing file.
Common situations: Configuring npx/node/python/uvx without that runtime installed or on PATH for the kernel; running the kernel as a service whose PATH differs from the interactive shell; executable bit not set after extracting a tool; typo in the command path; on macOS, an xcode-select / gatekeeping refusal.
Related errors
- command is required for stdio server
- unsupported server type: %s
- environment: %w
- stdin pipe: %w
- stdout pipe: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/bf4689be1d03c4d4.
Report an issue: GitHub.