argoproj/argo-workflows · error

offload node status is not supported

Error message

offload node status is not supported

What it means

ErrOffloadNotSupported is the sentinel error returned by every method of the explosiveOffloadNodeStatusRepo (Save, Get, List, Delete, ListOldOffloads). This repo is a no-op stand-in used when offloading node status to the database is disabled; calling it signals the caller expected offload storage that is not configured.

Source

Thrown at persist/sqldb/explosive_offload_node_status_repo.go:12

package sqldb

import (
	"context"
	"fmt"

	wfv1 "github.com/argoproj/argo-workflows/v4/pkg/apis/workflow/v1alpha1"
)

var (
	ExplosiveOffloadNodeStatusRepo OffloadNodeStatusRepo = &explosiveOffloadNodeStatusRepo{}
	ErrOffloadNotSupported                               = fmt.Errorf("offload node status is not supported")
)

type explosiveOffloadNodeStatusRepo struct{}

func (n *explosiveOffloadNodeStatusRepo) IsEnabled() bool {
	return false
}

func (n *explosiveOffloadNodeStatusRepo) Save(context.Context, string, string, wfv1.Nodes) (string, error) {
	return "", ErrOffloadNotSupported
}

func (n *explosiveOffloadNodeStatusRepo) Get(context.Context, string, string) (wfv1.Nodes, error) {
	return nil, ErrOffloadNotSupported
}

func (n *explosiveOffloadNodeStatusRepo) List(context.Context, string) (map[UUIDVersion]wfv1.Nodes, error) {
	return nil, ErrOffloadNotSupported

View on GitHub (pinned to 35bff19146)

Solutions

  1. Configure persistence (offload node status) in the workflow-controller-configmap so the real sqldb-backed offload repo is used instead of the explosive no-op.
  2. Guard callers with OffloadNodeStatusRepo.IsEnabled() before calling Save/Get/Delete.
  3. If writing tests, use the explosive repo only for paths that tolerate ErrOffloadNotSupported or mock the repo interface.
  4. Verify which repo the controller wired at startup (logs) and correct the wiring/config.

Example fix

// before
// nodes, err := offloadRepo.Get(ctx, wfNamespace, wfName)
// after
// if !offloadRepo.IsEnabled() {
//     return nil // or read status from the workflow object
// }
// nodes, err := offloadRepo.Get(ctx, wfNamespace, wfName)
Defensive patterns

Strategy: type-guard

Validate before calling

// check offloading before use
if !persist.OffloadNodeStatusRepo.IsEnabled() {
    return errors.New("node status offloading is disabled; configure persistence")
}

Type guard

func offloadAvailable(repo persist.OffloadNodeStatusRepo) bool {
    return repo != nil && repo.IsEnabled()
}

Try / catch

if err == persist.ErrOffloadNotSupported {
    logger.Info(ctx, "offload disabled; falling back to inline node status")
    return nil // read status from the Workflow object instead
}

Prevention

When it happens

Trigger: Any controller code path calls ExplosiveOffloadNodeStatusRepo.Save/Get/List/Delete/ListOldOffloads while node status offloading is not enabled (IsEnabled() == false), e.g. when the workflow archive database is not configured.

Common situations: Running without persistence configured (no postgres/mysql offload) while a code path or test assumes offload; manually injecting the explosive repo; misconfigured persistence block in the controller configmap.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/c614e3975760ffc1. Report an issue: GitHub.