{"record":{"id":"f8f8960c1a6d1021","repo":"siyuan-note/siyuan","slug":"stdin-pipe-w","errorCode":null,"errorMessage":"stdin pipe: %w","messagePattern":"stdin pipe: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/mcp/client/mcp.go","lineNumber":466,"sourceCode":"func connectStdio(ctx context.Context, client *mcp.Client, server conf.MCPServer) (*mcp.ClientSession, *exec.Cmd, error) {\n\tif server.Command == \"\" {\n\t\treturn nil, nil, fmt.Errorf(\"command is required for stdio server\")\n\t}\n\n\tcmd := exec.Command(server.Command, server.Args...)\n\tcmdEnv, err := buildStdioEnvironment(server, os.LookupEnv, func(value string) string {\n\t\tif model.Conf == nil {\n\t\t\treturn value\n\t\t}\n\t\treturn conf.ResolveSecretsVars(model.Conf.Secrets, model.Conf.Variables, value)\n\t}, runtime.GOOS)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"environment: %w\", err)\n\t}\n\tcmd.Env = cmdEnv\n\tstdin, err := cmd.StdinPipe()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"stdin pipe: %w\", err)\n\t}\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"stdout pipe: %w\", err)\n\t}\n\tcmd.Stderr = io.Discard\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"start command: %w\", err)\n\t}\n\n\tconnectCtx, connectCancel := context.WithTimeout(ctx, serverTimeout(server))\n\tdefer connectCancel()\n\ttransport := &mcp.IOTransport{Reader: stdout, Writer: stdin}\n\tsession, err := client.Connect(connectCtx, transport, nil)\n\tif err != nil {\n\t\tcmd.Process.Kill()\n\t\tcmd.Wait()","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/client/mcp.go#L448-L484","documentation":"Returned when exec.Cmd.StdinPipe() fails while wiring up the IOTransport for a stdio MCP server. StdinPipe allocates an OS pipe; failure means the kernel cannot create a pipe handle, not that the child process is misconfigured. The wrapped OS error (typically EMFILE/ENFILE on Unix or a handle-allocation failure on Windows) is preserved.","triggerScenarios":"connectStdio calls cmd.StdinPipe() and the OS refuses to allocate a new pipe. Common when the SiYuan process has hit its file-descriptor limit, when too many MCP child processes are already spawned, or when per-user process/handle quotas are exhausted.","commonSituations":"Many stdio MCP servers configured and started in parallel; a long-running kernel that has leaked file descriptors; containerized deployment with a low RLIMIT_NOFILE (e.g. systemd DefaultLimitNOFILE) or a low --ulimit on Docker.","solutions":["Check the wrapped error text for EMFILE/ENFILE or 'too many open files' and raise the kernel process's file-descriptor limit (ulimit -n, systemd LimitNOFILE=, Docker --ulimit nofile=).","Reduce the number of concurrently connected stdio MCP servers, or disable servers you are not actively using.","Run the kernel under a leak detector / lsof to confirm whether descriptors are being held after MCP servers disconnect; if so, that is a kernel bug worth reporting.","Retry connecting after freeing descriptors; the failure is environmental, not a permanent config defect."],"exampleFix":"# before: low fd limit on Linux\nulimit -n 1024\n# after\nulimit -n 65536","handlingStrategy":"retry","validationCode":"// Check available fd budget is reasonable before spawning a stdio MCP server.\nimport \"syscall\"\nfunc fdBudget() int {\n    var r syscall.Rlimit\n    if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &r); err != nil { return -1 }\n    return int(r.Cur)\n}","typeGuard":null,"tryCatchPattern":"// Distinguish EMFILE/ENFILE from other errors; only retry resource errors after backoff.\nif errors.Is(err, syscall.EMFILE) || errors.Is(err, syscall.ENFILE) {\n    // backoff and retry connectStdio once\n}","preventionTips":["Set a generous RLIMIT_NOFILE for the kernel process.","Limit the number of concurrently connected stdio MCP servers.","Monitor fd usage (lsof -p <pid>) to detect leaks early."],"tags":["mcp","stdio","os-resource","file-descriptors"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}