BornToBeRoot/NETworkManager · error · Exception
string.Join("; ", ps.Streams.Error)
Error message
string.Join("; ", ps.Streams.Error) What it means
SetRuleEnabledAsync runs Enable-NetFirewallRule or Disable-NetFirewallRule in a shared PowerShell runspace. If the cmdlet writes any records to the error stream, the method wraps them (joined with "; ") in a generic System.Exception and throws. The message is the raw PowerShell error text, typically a non-terminating error such as a rule name that does not exist.
Solutions
- Run the application elevated (as administrator) before calling firewall APIs.
- Re-fetch the rule list with GetRulesAsync and retry with a fresh FirewallRule whose Id still exists.
- Catch the exception and surface the joined PowerShell error text to the user, since it contains the actual NetSecurity cmdlet error.
- Verify the rule name manually with PowerShell: Enable-NetFirewallRule -Name '<rule.Id>' to reproduce the error text.
Example fix
// before
await Firewall.SetRuleEnabledAsync(staleRule, true);
// after
var rules = await Firewall.GetRulesAsync();
var fresh = rules.FirstOrDefault(r => r.Id == staleRule.Id) ?? throw new InvalidOperationException($"Rule {staleRule.Id} no longer exists");
await Firewall.SetRuleEnabledAsync(fresh, true); Defensive patterns
Strategy: try-catch
Validate before calling
// refresh and verify the rule exists before toggling
var rules = await Firewall.GetRulesAsync();
if (!rules.Any(r => r.Id == rule.Id)) throw new InvalidOperationException($"Firewall rule '{rule.Id}' no longer exists"); Type guard
static bool RuleExists(IEnumerable<FirewallRule> rules, FirewallRule rule) => rules.Any(r => r != null && !string.IsNullOrEmpty(r.Id) && r.Id == rule.Id);
Try / catch
try
{
await Firewall.SetRuleEnabledAsync(rule, enabled);
}
catch (Exception ex) when (ex.Message.Contains("NetFirewallRule"))
{
Log.Warn($"Firewall toggle failed: {ex.Message}");
// surface ex.Message (PowerShell error text) to the user
} Prevention
- Always run elevated when touching Windows Firewall rules.
- Refresh the rule list before acting on a cached FirewallRule object.
- Log the full joined error text; localized Windows messages carry the real cause.
When it happens
Trigger: Calling SetRuleEnabledAsync(rule, enabled) when rule.Id does not match an existing firewall rule name (e.g. the rule was deleted externally or the Id is stale from a cached GetRulesAsync snapshot), or when the process lacks admin rights so the NetSecurity cmdlet fails.
Common situations: App not running elevated (NetFirewall cmdlets require administrator); a stale FirewallRule object after the rule was removed by another tool or group policy refresh; localized Windows error text making the message hard to parse.
Related errors
- string.Join("; ", ps.Streams.Error.Select(e =>…
- Error while retrieving TCP table
- Could not load PSDiscoveryProtocol.psm1
- Win32Exception for native error code (int)result
- message (joined PowerShell error streams)
AI-assisted analysis of BornToBeRoot/NETworkManager@2780d65469 (2026-09-12).
Data as JSON: /api/errors/72758e772c38177f.
Report an issue: GitHub.
Appendix: source
Thrown at Source/NETworkManager.Models/Firewall/Firewall.cs:198
/// </param>
/// <exception cref="Exception">
/// Thrown when the PowerShell pipeline reports one or more errors.
/// </exception>
public static async Task SetRuleEnabledAsync(FirewallRule rule, bool enabled)
{
await RunspaceLock.WaitAsync();
try
{
await Task.Run(() =>
{
using var ps = SMA.PowerShell.Create();
ps.Runspace = SharedRunspace;
ps.AddScript($@"{(enabled ? "Enable" : "Disable")}-NetFirewallRule -Name '{rule.Id}'");
ps.Invoke();
if (ps.Streams.Error.Count > 0)
throw new Exception(string.Join("; ", ps.Streams.Error));
});
}
finally
{
RunspaceLock.Release();
}
}
/// <summary>
/// Permanently removes the given <paramref name="rule"/> by running
/// <c>Remove-NetFirewallRule</c> against the rule's internal <see cref="FirewallRule.Id"/>.
/// </summary>
/// <param name="rule">
/// The firewall rule to delete.
/// </param>
/// <exception cref="Exception">
/// Thrown when the PowerShell pipeline reports one or more errors.
/// </exception>View on GitHub (pinned to 2780d65469)