argoproj/argo-workflows · error

AuthSupplier cannot be empty when connecting to Argo Server

Error message

AuthSupplier cannot be empty when connecting to Argo Server

What it means

When connecting over HTTP1 to the Argo Server (opts.ArgoServerOpts.HTTP1, used for HTTP fallback / proxies / event streams), the client authenticates using a caller-supplied AuthSupplier. There is no default credential source in this mode, so a nil AuthSupplier is rejected rather than producing an unauthenticated client.

Source

Thrown at pkg/apiclient/apiclient.go:78

		}
		logFormat, err := logging.TypeFromStringOr(opts.LogFormat, logging.Text)
		if err != nil {
			return nil, nil, err
		}
		log = logging.NewSlogLogger(logLevel, logFormat)
		ctx = logging.WithLogger(ctx, log)
	}
	log.WithField("opts", opts).Debug(ctx, "Client options")
	if opts.Offline {
		return newOfflineClient(ctx, opts.OfflineFiles)
	}
	if opts.ArgoServerOpts.URL != "" && opts.InstanceID != "" {
		return nil, nil, fmt.Errorf("cannot use instance ID with Argo Server")
	}
	switch {
	case opts.ArgoServerOpts.HTTP1:
		if opts.AuthSupplier == nil {
			return nil, nil, fmt.Errorf("AuthSupplier cannot be empty when connecting to Argo Server")
		}
		return newHTTP1Client(ctx, opts.ArgoServerOpts, opts.AuthSupplier(), opts.Proxy)
	case opts.ArgoServerOpts.URL != "":
		if opts.AuthSupplier == nil {
			return nil, nil, fmt.Errorf("AuthSupplier cannot be empty when connecting to Argo Server")
		}
		return newArgoServerClient(ctx, opts.ArgoServerOpts, opts.AuthSupplier())
	default:
		if opts.ClientConfigSupplier != nil {
			opts.ClientConfig = opts.ClientConfigSupplier()
		}
		return newArgoKubeClient(ctx, opts.ArgoKubeOpts, opts.ClientConfig, instanceid.NewService(opts.InstanceID))
	}
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Set Opts.AuthSupplier to a func returning your auth token (e.g. () -> "Bearer <token>")
  2. If using the argo CLI, don't hand-build Opts — use the CLI's client factory which supplies auth automatically
  3. If you only need the gRPC path, clear HTTP1 and set URL with AuthSupplier or use ClientConfigSupplier for direct-kube

Example fix

// before
opts := apiclient.Opts{ArgoServerOpts: apiclient.ArgoServerOpts{URL: url, HTTP1: true}}
// after
opts := apiclient.Opts{ArgoServerOpts: apiclient.ArgoServerOpts{URL: url, HTTP1: true}, AuthSupplier: func() string { return token }}
Defensive patterns

Strategy: validation

Validate before calling

func newHTTP1Opts(url, token string) (apiclient.Opts, error) {
    if token == "" {
        return apiclient.Opts{}, errors.New("token required for HTTP1 Argo Server access (set ARGO_TOKEN)")
    }
    return apiclient.Opts{
        ArgoServerOpts: apiclient.ArgoServerOpts{URL: url, HTTP1: true},
        AuthSupplier:   func() string { return "Bearer " + token },
    }, nil
}

Prevention

When it happens

Trigger: NewClientFromOptsWithContext with Opts{ArgoServerOpts: {URL: ..., HTTP1: true}} and AuthSupplier nil — e.g. constructing Opts by hand without the wiring the CLI normally performs (which sets AuthSupplier from the k8s token/SSO).

Common situations: Custom Go programs using pkg/apiclient with HTTP1 enabled; environments where ARGO_TOKEN/auth wiring was skipped; testing HTTP1 mode directly without replicating the CLI's auth setup.

Related errors


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