Skip to content

Dashboard "Errored" segment counts stale-reporting hosts, not failed jobs #929

Description

@9technologygroup

What is the installation method of your PatchMon server?

Other

What is the version of your PatchMon server?

Not specified by reporter — code below verified against main @ 2.0.3

Description

Filed on behalf of a community report. Healthy hosts show up in the red "Errored" segment of the dashboard's Update Status chart, causing a mismatch between the chart and the actual host list.

Reporter's example — this host is counted as Errored despite its most recent job completing successfully:

SERVER1       | completed | 2026-05-05 12:44:06  ← latest job
SERVER1       | completed | 2026-05-05 12:44:00
SERVER1       | failed    | 2026-05-05 12:43:34  ← old job

The reporter attributed this to job_history (any host with at least one failed row being counted). That diagnosis does not match current code — I checked, and the actual mechanism is different. Recording it here so the real cause isn't lost.

The "Errored" count never touches job_history. It comes from GetDashboardStats:

server-source-code/internal/sqlc/queries/dashboard.sql:5

COUNT(*) FILTER (WHERE status = 'active' AND last_update < $1)::int AS errored_hosts,
COUNT(*) FILTER (WHERE status = 'active' AND last_update < $2)::int AS offline_hosts,

where $1 is now - (2 × update_interval_minutes) and $2 is now - (3 × update_interval_minutes)server-source-code/internal/store/dashboard.go:43-45. It is surfaced as the "Errored" bucket at server-source-code/internal/store/dashboard.go:112-116.

So "Errored" is a reporting-staleness check on hosts.last_update, not a failure count. It is the same predicate as offline_hosts with a tighter window. job_history is only read for the per-host Agent Activity feed (ListJobHistoryByApiID), never for dashboard aggregates.

Two problems follow:

  1. The label is misleading. A red segment named "Errored" reads as "patching/jobs failed", but it measures "hasn't checked in within 2× its update interval". Elsewhere in the app the exact same condition is called inactive / stale (dashboard.sql:112-121). A host that is healthy but reporting slightly slower than 2× its interval is labelled Errored — which is what the reporter is most likely hitting.
  2. It overlaps offline_hosts. Every errored host is also counted as offline once the 3× window passes, with no visible distinction between the two buckets.

Steps to reproduce

  1. Have an active host whose last_update is older than 2 × update_interval_minutes (e.g. an agent reporting on a slower cadence, or one that briefly missed a check-in).
  2. Open the dashboard and look at the Update Status chart.
  3. The host is counted in the red "Errored" segment even though its jobs are completing successfully.

Expected behavior

Either:

  • the segment counts hosts whose latest job actually failed (i.e. genuinely errored), or
  • it is renamed to reflect what it measures — e.g. "Not reporting" / "Stale" — so it stops being read as a job-failure count.

Whichever way it goes, the thresholds should be documented, since vs the update interval is the only thing separating "Errored" from "Offline".

Additional context

Reporter did not state a version. If their instance predates the Go rewrite (v1.5.0), the legacy JS backend may have computed this differently and the original job_history diagnosis could be accurate for that version — worth confirming before closing.

Related: the drill-through from this same chart segment navigates to the wrong filter — #930.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Fields

    Priority

    Medium

    Effort

    Medium

    Projects

    Status
    Released into Main

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions