Skip to content

Commit e898048

Browse files
yotsudaclaude
andcommitted
chore(diagnostic): log exception type + stack trace when polling-engine outer catch fires
Captures Exception.GetType().FullName, Message, ScriptStackTrace, .NET StackTrace, and InnerException details to %TEMP%/mcp-polling-engine-error.log on each outer-catch hit. Triggered by an intermittent "Operation is not valid due to the current state of the object" the user saw whose source isn't yet identified. Without a stack trace we can only guess between Format-McpOutput, Get-Location, the Console.SetOut/SetError restore sequence, the _externalUI reflection swap, or PSReadLine timing. The log will pin it to the failing line on next reproduction. Wrapped in try/catch so any failure of the diagnostic itself (file I/O, Add-Content lock contention) cannot mask or replace the original exception that brought us into this catch. REMOVE this block once the underlying cause has been identified and fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 80ea624 commit e898048

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

PowerShell.MCP/Resources/MCPPollingEngine.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,41 @@ if (-not (Test-Path Variable:global:McpTimer)) {
895895
catch {
896896
$errorMessage = "Command execution failed: $($_.Exception.Message)"
897897
Write-Host $errorMessage -ForegroundColor Red
898+
# Diagnostic: capture stack trace + exception type so we can
899+
# locate the failing code path the next time this fires.
900+
# Triggered by an intermittent "Operation is not valid due
901+
# to the current state of the object" the user saw whose
902+
# source isn't yet identified — remove this block once the
903+
# underlying cause has been pinned down.
904+
try {
905+
$diagPath = Join-Path $env:TEMP 'mcp-polling-engine-error.log'
906+
$stamp = Get-Date -Format 'yyyy-MM-ddTHH:mm:ss.fff'
907+
$cmdSnippet = if ($cmd) { $cmd.Substring(0, [Math]::Min(200, $cmd.Length)) } else { '<null>' }
908+
$exType = $_.Exception.GetType().FullName
909+
$exMsg = $_.Exception.Message
910+
$scriptST = if ($_.ScriptStackTrace) { $_.ScriptStackTrace } else { '<null>' }
911+
$netST = if ($_.Exception.StackTrace) { $_.Exception.StackTrace } else { '<null>' }
912+
$inner = $_.Exception.InnerException
913+
$innerType = if ($inner) { $inner.GetType().FullName } else { '<none>' }
914+
$innerMsg = if ($inner) { $inner.Message } else { '' }
915+
$innerST = if ($inner -and $inner.StackTrace) { $inner.StackTrace } else { '' }
916+
$diagText = @"
917+
===== $stamp =====
918+
Pipeline (truncated): $cmdSnippet
919+
Exception type: $exType
920+
Message: $exMsg
921+
ScriptStackTrace:
922+
$scriptST
923+
.NET StackTrace:
924+
$netST
925+
InnerException type: $innerType
926+
InnerException message: $innerMsg
927+
InnerException StackTrace:
928+
$innerST
929+
930+
"@
931+
Add-Content -Path $diagPath -Value $diagText -Encoding UTF8
932+
} catch {}
898933
$mcpOutput = $errorMessage
899934
}
900935
finally {

0 commit comments

Comments
 (0)