{"record":{"id":"a4cd9b9d3ce78067","repo":"shadowsocks/shadowsocks-windows","slug":"cannot-find-the-plugin-program-file","errorCode":null,"errorMessage":"Cannot find the plugin program file","messagePattern":"Cannot find the plugin program file","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"shadowsocks-csharp/Controller/Service/Sip003Plugin.cs","lineNumber":112,"sourceCode":"                var localPort = GetNextFreeTcpPort();\r\n                LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort);\r\n\r\n                _pluginProcess.StartInfo.Environment[\"SS_LOCAL_HOST\"] = LocalEndPoint.Address.ToString();\r\n                _pluginProcess.StartInfo.Environment[\"SS_LOCAL_PORT\"] = LocalEndPoint.Port.ToString();\r\n                _pluginProcess.StartInfo.Arguments = ExpandEnvironmentVariables(_pluginProcess.StartInfo.Arguments, _pluginProcess.StartInfo.EnvironmentVariables);\r\n                try\r\n                {\r\n                    _pluginProcess.Start();\r\n                }\r\n                catch (System.ComponentModel.Win32Exception ex)\r\n                {\r\n                    // do not use File.Exists(...), it can not handle the scenarios when the plugin file is in system environment path.\r\n                    // https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values\r\n                    //if ((uint)ex.ErrorCode == 0x80004005)\r\n                    //  https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d\r\n                    if (ex.NativeErrorCode == 0x00000002)\r\n                    {\r\n                        throw new FileNotFoundException(I18N.GetString(\"Cannot find the plugin program file\"), _pluginProcess.StartInfo.FileName, ex);\r\n                    }\r\n                    throw new ApplicationException(I18N.GetString(\"Plugin Program\"), ex);\r\n                }\r\n                _pluginJob.AddProcess(_pluginProcess.Handle);\r\n                _started = true;\r\n            }\r\n\r\n            return true;\r\n        }\r\n\r\n        public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null)\r\n        {\r\n            // Expand the environment variables from the new process itself\r\n            if (environmentVariables != null)\r\n            {\r\n                foreach(string key in environmentVariables.Keys)\r\n                {\r\n                    name = name.Replace($\"%{key}%\", environmentVariables[key]);\r","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs#L94-L130","documentation":"Thrown as FileNotFoundException when Process.Start fails with a Win32Exception whose NativeErrorCode is 0x00000002 (ERROR_FILE_NOT_FOUND). It means the Sip003 plugin executable named in StartInfo.FileName could not be located on disk or resolved through the system PATH. The inner Win32Exception is preserved, and the message reports the resolved filename.","triggerScenarios":"Plugin configured with a bare command name (e.g. \"v2ray-plugin\") that is neither in the working directory nor on PATH; a relative path that resolves against the wrong working directory; plugin file deleted/moved after config was written; PATH not inherited because the app was launched from a context with a restricted environment.","commonSituations":"User installs a plugin to a custom folder and only sets the filename without full path; portable distribution where the plugin is bundled but PATH is not set; running as a service under an account whose PATH differs from the interactive user; typo in the plugin command.","solutions":["Set the plugin command to an absolute path to the executable.","Add the plugin's directory to the system PATH (and restart the app so it inherits the new PATH).","Verify the file exists at the resolved location and the app has execute/read permission on it.","Check the StartInfo.FileName actually being passed (environment variables may not be expanded)."],"exampleFix":"// before\n_pluginProcess.StartInfo.FileName = \"v2ray-plugin\"; // not on PATH\n\n// after\n_pluginProcess.StartInfo.FileName = @\"C:\\Tools\\v2ray-plugin\\v2ray-plugin.exe\";","handlingStrategy":"validation","validationCode":"// Resolve the plugin path before starting\nstring resolved = ExpandEnvironmentVariables(plugin.Command);\nif (!File.Exists(resolved) && !IsOnPath(resolved))\n    throw new FileNotFoundException(\"Plugin not found\", resolved);","typeGuard":"bool PluginPathLooksValid(string p) =>\n    !string.IsNullOrWhiteSpace(p) &&\n    (Path.IsPathRooted(p) || p.IndexOf(Path.DirectorySeparatorChar) >= 0 || IsOnPath(p));","tryCatchPattern":"try { plugin.Start(); }\ncatch (FileNotFoundException ex) when (ex.Message.Contains(\"plugin program file\"))\n{ /* tell user to set full path or install plugin on PATH */ }","preventionTips":["Store plugin commands as absolute paths in config.","On startup, verify each configured plugin file is reachable from the app's account.","Document that bare names require the plugin directory on the system PATH."],"tags":["plugin","sip003","process","file-not-found","path"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}