Describe the bug
After a Windows Update reconfigures installed MSI products (triggering Windows Modules Installer), PDH performance counter handles become invalid. The win_perf_counters plugin then fails on every scrape cycle with pdhErr=258 but:
- The error is only logged at
D! (Debug) level via log.Printf("D! metric init has error: %v", err)
- The
Gather() function returns nil (no error) to the caller
- The OTel scrape controller in
receiver/adapter/receiver.go treats this as a successful scrape with zero metrics
- No metrics are sent to CloudWatch, but the agent continues running with no visible indication of failure
This results in silent metric loss in production. The only way to detect the problem is through external alarms on missing datapoints. The only recovery is to restart the agent process.
Steps to reproduce
- Run CloudWatch Agent on Windows with
win_perf_counters collecting LogicalDisk metrics
- Allow Windows Update to run (specifically
Windows Modules Installer / TrustedInstaller MSI reconfiguration)
- After the update, the agent continues running but stops sending metrics
What did you expect to see?
- The agent should either recover by re-initializing PDH counter handles, or
- Log an
E! (Error) level message indicating metrics collection has failed, or
- Return an error from
Gather() so the OTel pipeline can report the failure
What did you see instead?
Agent process running, log file growing. Zero metrics reaching CloudWatch. CloudWatch alarm triggered after 70 minutes of missing data. Agent does not self-recover.
Service stop succeeded (SCM reported stopped), but agent processes remained running.

Service restart created a third process and all three coexisted, none delivering metrics. taskkill /F failed with Access Denied. Only an instance reboot resolved the situation, causing production downtime.
Agent log after PDH counter invalidation (debug level enabled):
# First failed scrape:
2026-07-11T18:50:42Z D! {"caller":"adapter/receiver.go:61","msg":"Begin scraping metrics with adapter","receiver":"win_perf_counters"}
2026-07-11T18:50:43Z D! metric init has error: (pdhErr=258) The system cannot find message text for message number 0x%1 in the message file for %2.
# Same error repeating indefinitely without escalation or recovery, only resolvable via instance reboot:
2026-07-14T11:41:42Z D! {"caller":"adapter/receiver.go:61","msg":"Begin scraping metrics with adapter","receiver":"win_perf_counters"}
2026-07-14T11:41:43Z D! metric init has error: (pdhErr=258) The system cannot find message text for message number 0x%1 in the message file for %2.
# Note: At default log level (info/warn), these lines would be completely invisible.
# No E! or W! is ever emitted. Gather() returns nil. Agent reports healthy.
Note: The logged value pdhErr=258 may represent a PDH status code that FormatMessage() cannot resolve (the error text "The system cannot find message text..." is the FormatMessage failure itself, not the PDH error description). The underlying PDH status is unclear from the log alone.
What version did you use?
Version: CWAgent/1.300069.0b1529 (go1.26.3; windows; amd64)
What config did you use?
Agent configured with win_perf_counters collecting LogicalDisk % Free Space metrics with dimensions [instance = C:], [InstanceId], [objectname = LogicalDisk]. Namespace: custom namespace. Collection interval: 60s.
Environment
OS: Windows Server 2016 (EC2, eu-central-1)
Agent running as: Windows Service (AmazonCloudWatchAgent)
Additional context
We traced the behavior to the following code pattern in plugins/inputs/win_perf_counters/win_perf_counters.go (Gather() method):
Note: Code references are based on the current main branch. The CWA fork may differ slightly from Telegraf upstream.
if !metric.initialized {
if err := metric.init(); err != nil {
log.Printf("D! metric init has error: %v", err)
continue // skips this metric silently
}
}
// ...
return nil // always returns nil, never an error
The item.init() method calls PdhOpenQuery and PdhAddEnglishCounter. After Windows Update invalidates the counter registry, these calls fail. The initialized field remains false, so init() is retried every cycle, but the error is never escalated.
In receiver/adapter/receiver.go, scrape() checks the return value of Gather():
if err := r.input.Input.Gather(r.accumulator); err != nil {
// never reached because Gather() always returns nil
}
return r.accumulator.GetOtelMetrics(), nil // empty metrics, no error
Possible approaches (just ideas, not prescriptive):
- Escalate to
W! or E! after N consecutive init() failures
- Return an error from
Gather() when all metrics fail to initialize
- Attempt a full PDH handle re-initialization (close + reopen) periodically
The trigger in our case correlates with Windows Event ID 1035 (MsiInstaller reconfiguration of ~60 products including VC++ runtimes and the CloudWatch Agent MSI itself), caused by routine Windows Update activity (Windows Modules Installer / TrustedInstaller). The first missing CloudWatch datapoint aligns with this activity.
Related: #223 (Windows service two-process model)
Limitations of this report
- We did not run
lodctr /R, winmgmt /resyncperf, or typeperf "\LogicalDisk(*)\% Free Space" before rebooting, so we cannot confirm whether PDH was broken system-wide or only within the agent process.
- No
Microsoft-Windows-PerfCtrs events (ID 1008/1023) were found in the event log, but we did not specifically filter for this source at the time.
Describe the bug
After a Windows Update reconfigures installed MSI products (triggering
Windows Modules Installer), PDH performance counter handles become invalid. Thewin_perf_countersplugin then fails on every scrape cycle withpdhErr=258but:D!(Debug) level vialog.Printf("D! metric init has error: %v", err)Gather()function returnsnil(no error) to the callerreceiver/adapter/receiver.gotreats this as a successful scrape with zero metricsThis results in silent metric loss in production. The only way to detect the problem is through external alarms on missing datapoints. The only recovery is to restart the agent process.
Steps to reproduce
win_perf_counterscollectingLogicalDiskmetricsWindows Modules Installer/ TrustedInstaller MSI reconfiguration)What did you expect to see?
E!(Error) level message indicating metrics collection has failed, orGather()so the OTel pipeline can report the failureWhat did you see instead?
Agent process running, log file growing. Zero metrics reaching CloudWatch. CloudWatch alarm triggered after 70 minutes of missing data. Agent does not self-recover.
Service stop succeeded (SCM reported stopped), but agent processes remained running.

Service restart created a third process and all three coexisted, none delivering metrics.
taskkill /Ffailed with Access Denied. Only an instance reboot resolved the situation, causing production downtime.Agent log after PDH counter invalidation (debug level enabled):
Note: The logged value
pdhErr=258may represent a PDH status code thatFormatMessage()cannot resolve (the error text "The system cannot find message text..." is the FormatMessage failure itself, not the PDH error description). The underlying PDH status is unclear from the log alone.What version did you use?
Version:
CWAgent/1.300069.0b1529 (go1.26.3; windows; amd64)What config did you use?
Agent configured with
win_perf_counterscollectingLogicalDisk % Free Spacemetrics with dimensions[instance = C:],[InstanceId],[objectname = LogicalDisk]. Namespace: custom namespace. Collection interval: 60s.Environment
OS: Windows Server 2016 (EC2, eu-central-1)
Agent running as: Windows Service (AmazonCloudWatchAgent)
Additional context
We traced the behavior to the following code pattern in
plugins/inputs/win_perf_counters/win_perf_counters.go(Gather()method):Note: Code references are based on the current
mainbranch. The CWA fork may differ slightly from Telegraf upstream.The
item.init()method callsPdhOpenQueryandPdhAddEnglishCounter. After Windows Update invalidates the counter registry, these calls fail. Theinitializedfield remainsfalse, soinit()is retried every cycle, but the error is never escalated.In
receiver/adapter/receiver.go,scrape()checks the return value ofGather():Possible approaches (just ideas, not prescriptive):
W!orE!after N consecutiveinit()failuresGather()when all metrics fail to initializeThe trigger in our case correlates with Windows Event ID 1035 (MsiInstaller reconfiguration of ~60 products including VC++ runtimes and the CloudWatch Agent MSI itself), caused by routine Windows Update activity (
Windows Modules Installer/ TrustedInstaller). The first missing CloudWatch datapoint aligns with this activity.Related: #223 (Windows service two-process model)
Limitations of this report
lodctr /R,winmgmt /resyncperf, ortypeperf "\LogicalDisk(*)\% Free Space"before rebooting, so we cannot confirm whether PDH was broken system-wide or only within the agent process.Microsoft-Windows-PerfCtrsevents (ID 1008/1023) were found in the event log, but we did not specifically filter for this source at the time.