Skip to content

Application.Status.Resources[].Health is not populated when GetApplication is called with refresh=true #24832

@vr009

Description

@vr009

Checklist:

  • I've searched in the docs and FAQ for my answer: https://bit.ly/argocd-faq.
  • I've included steps to reproduce the bug.
  • I've pasted the output of argocd version.

Describe the bug

After upgrading to ArgoCD 3.x (where --persist-resource-health=false by default), the Application.Status.Resources[].Health field is not populated when calling the API GetApplication with refresh=true, even though:

  • Application.Status.ResourceHealthSource is set to "appTree"
  • The ArgoCD UI displays health statuses correctly
  • The same API call without refresh=true returns health statuses correctly
  • The health data exists in Redis cache

To Reproduce

  1. Deploy ArgoCD 3.x with default settings (where --persist-resource-health=false)
  2. Create an application with multiple resources
  3. Call the ArgoCD API: GetApplication with parameter refresh=true
    curl -H "Authorization: Bearer $TOKEN" \
      "https://argocd-server/api/v1/applications/my-app?refresh=true"
  4. Observe that status.resources[].health is null for all resources
  5. Call the same API without refresh=true:
    curl -H "Authorization: Bearer $TOKEN" \
      "https://argocd-server/api/v1/applications/my-app"
  6. Observe that status.resources[].health is properly populated

Expected behavior

When calling GetApplication with refresh=true, the Application.Status.Resources[].Health field should be populated with health statuses from the ApplicationTree cache (Redis), just like when calling without refresh.

The health statuses should be consistent regardless of whether refresh parameter is used or not.

Root Cause

The issue is in the Get() method in server/application/application.go:

  1. Line 777: inferResourcesStatusHealth(a) is called for the initial application object
  2. Lines 796-862: When refresh != nil, the code waits for an updated application from the broadcaster
  3. Line 858: The updated application is returned via event.Application.DeepCopy() without calling inferResourcesStatusHealth() again

This means the refreshed application object never gets its health statuses populated from the cache.

Code Reference

https://github.com/argoproj/argo-cd/blob/master/server/application/application.go#L757-L863

The fix should be to call s.inferResourcesStatusHealth() on the application object before returning it on line 858:

case event := <-events:
    if appVersion, err := strconv.Atoi(event.Application.ResourceVersion); err == nil && appVersion > minVersion {
        annotations := event.Application.GetAnnotations()
        if annotations == nil {
            annotations = make(map[string]string)
        }
        if _, ok := annotations[v1alpha1.AnnotationKeyRefresh]; !ok {
            refreshedApp := event.Application.DeepCopy()
            s.inferResourcesStatusHealth(refreshedApp)  // added this line
            return refreshedApp, nil
        }
    }

Version

argocd-server: v3.1.7+511ebd7
  BuildDate: 2025-09-22T22:21:06Z
  GitCommit: 511ebd799e64f9af6484feaa84a5e718a77620d5
  GitTreeState: clean
  GoVersion: go1.24.6
  Compiler: gc
  Platform: linux/amd64
  Kustomize Version: v5.7.0 2025-06-28T07:00:07Z
  Helm Version: v3.18.4+gd80839c
  Kubectl Version: v0.33.1
  Jsonnet Version: v0.21.0

Additional Context

  • Related to issue: Persist resource health in Redis instead of the Application CR by default #10312
  • The default value of --persist-resource-health changed to false in v3.0 for optimization
  • When persist-resource-health=false, health statuses should come from Redis (ApplicationTree) instead of CR
  • The inferResourcesStatusHealth() function (line 2776) correctly retrieves health from cache when ResourceHealthSource == ResourceHealthLocationAppTree
  • This bug affects any client that uses refresh=true parameter (like backend services monitoring application health)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcomponent:serverIssue related to the Server componentregressionBug is a regression, should be handled with high priority

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions