2dust/v2rayN · error · ApplicationException

Set Internet Proxy failed with error code

Error message

Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}

What it means

Thrown after the WinInet InternetSetOption/InternetSetPerConnOptions call sequence returns a non-zero (failure) result. The message appends Marshal.GetLastWin32Error() so the Win32 error code is visible. It signals Windows declined to apply the system proxy configuration.

Solutions

  1. Run v2rayN as administrator when setting the system proxy.
  2. Decode GetLastWin32Error (e.g. 'net helpmsg <code>') to identify the specific Win32 failure.
  3. Close browsers/other proxy-managing apps that may lock WinInet settings and retry.
  4. Ensure a network connection is active (WinInet refuses some options when no connection is up).
  5. If running as a service/session 0, set the proxy from an interactive user session instead.

Example fix

// before
throw new ApplicationException($"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}");

// after - include the symbolic message for faster diagnosis
var code = Marshal.GetLastWin32Error();
throw new ApplicationException($"Set Internet Proxy failed (Win32 {code}): {new System.ComponentModel.Win32Exception(code).Message}");
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort pre-check: require admin and an active connection before setting proxy
if (!OperatingSystem.IsWindows()) throw new PlatformNotSupportedException();
// caller should ensure elevated session and an active network connection

Type guard

static bool CanSetWindowsProxy() => OperatingSystem.IsWindows();

Try / catch

try
{
    ProxySettingWindows.SetProxy(/* ... */);
}
catch (ApplicationException ex) when (ex.Message.Contains("Set Internet Proxy failed"))
{
    var msg = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message;
    _log?.Error($"WinInet set proxy failed: {msg}");
}

Prevention

When it happens

Trigger: The proxy-setting routine builds an INTERNET_PER_CONN_OPTION_LIST, calls the WinInet set-option API, and returnvalue != 0 (the API reported failure). GetLastWin32Error yields the specific code (e.g. network unavailable, access denied).

Common situations: Running without administrator privileges on some Windows configurations; active/networked dial-up or VPN interfering with per-connection options; another process holds the WinInet settings lock; corrupt WinInet registry entries; calling on a non-interactive/session-0 context.

Related errors


AI-assisted analysis of 2dust/v2rayN@e01717d832 (2026-08-13). Data as JSON: /api/errors/a4d7596a917305ac. Report an issue: GitHub.

Appendix: source

Thrown at v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs:194

        // FREE the data ASAP
        if (list.szConnection != nint.Zero)
        {
            Marshal.FreeHGlobal(list.szConnection); // release mem 3
        }
        if (optionCount > 1)
        {
            Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1
            if (optionCount > 2)
            {
                Marshal.FreeHGlobal(options[2].m_Value.m_StringPtr); // release mem 2
            }
        }
        Marshal.FreeCoTaskMem(optionsPtr); // release mem 4
        Marshal.FreeCoTaskMem(ipcoListPtr); // release mem 5
        if (returnvalue != 0)
        {
            // throw the error codes, they might be helpful
            throw new ApplicationException($"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}");
        }

        return true;
    }

    /// <summary>
    /// Retrieve list of connections including LAN and WAN to support PPPoE connection
    /// </summary>
    /// <returns>A list of RAS connection names. May be empty list if no dial up connection.</returns>
    /// <exception cref="ApplicationException">Error message with win32 error code</exception>
    private static IEnumerable<string> EnumerateRasEntries()
    {
        var entries = 0;
        // attempt to query with 1 entry buffer
        var rasEntryNames = new RASENTRYNAME[1];
        var bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME));
        rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME));

View on GitHub (pinned to e01717d832)