argoproj/argo-workflows · error

failed to create HTTP client: %w

Error message

failed to create HTTP client: %w

What it means

newSso builds a custom HTTP client (used for OIDC discovery and token exchange) from the InsecureSkipVerify and RootCA config via createHTTPClient. If that helper fails — typically because the configured RootCA cannot be parsed or read — construction is aborted and the underlying cause is wrapped with this message.

Source

Thrown at server/auth/sso/sso.go:146

	if c.ClientID.Name == "" || c.ClientID.Key == "" {
		return nil, fmt.Errorf("clientID empty")
	}
	if c.ClientSecret.Name == "" || c.ClientSecret.Key == "" {
		return nil, fmt.Errorf("clientSecret empty")
	}
	clientSecretObj, err := secretsIf.Get(ctx, c.ClientSecret.Name, metav1.GetOptions{})
	if err != nil {
		return nil, err
	}

	// Create http client
	httpClientConfig := HTTPClientConfig{
		InsecureSkipVerify: c.InsecureSkipVerify,
		RootCA:             c.RootCA,
	}
	httpClient, err := createHTTPClient(httpClientConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create HTTP client: %w", err)
	}

	oidcContext := oidc.ClientContext(ctx, httpClient)
	// Some offspec providers like Azure, Oracle IDCS have oidc discovery url different from issuer url which causes issuerValidation to fail
	// This providerCtx will allow the Verifier to succeed if the alternate/alias URL is in the config
	if c.IssuerAlias != "" {
		oidcContext = oidc.InsecureIssuerURLContext(oidcContext, c.IssuerAlias)
	}

	provider, err := factory(oidcContext, c.Issuer)
	if err != nil {
		return nil, err
	}
	// Claims is implemented by oidc.Provider and contains the discovery
	// metadata, including the optional end_session_endpoint.
	var providerMetadata struct {
		EndSessionEndpoint string `json:"end_session_endpoint"`
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped %w cause to identify the actual failure (bad PEM vs unreadable resource)
  2. Verify sso.rootCA.secretName.keySelector or rootCA.configMapName.key points to a valid PEM-encoded CA cert and that the object exists
  3. Grant argo-server RBAC read access to the referenced secret/configmap
  4. As a diagnostic only, test with the same setup but InsecureSkipVerify enabled, then fix the CA chain properly

Example fix

# before
sso:
  rootCA:
    configMapName: argo-root-ca
    key: ca.crt   # key does not exist in the configmap
# after
sso:
  rootCA:
    configMapName: argo-root-ca
    key: root-ca.pem  # valid PEM bundle present in the configmap
Defensive patterns

Strategy: validation

Validate before calling

if cfg.RootCA != nil {
    var caPEM []byte
    // fetch from configmap/secret
    if ok := x509.NewCertPool().AppendCertsFromPEM(caPEM); !ok {
        return fmt.Errorf("rootCA is not a valid PEM certificate bundle")
    }
}

Try / catch

if _, err := sso.New(ctx, cfg, secretsIf, baseHRef, secure); err != nil {
    var pe *tls.CertificateVerificationError
    if errors.As(err, &pe) || strings.Contains(err.Error(), "failed to create HTTP client") {
        return fmt.Errorf("check sso.rootCA reference and PEM validity: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling New with sso.rootCA.secretName/rootCA.configMapName pointing at a missing, unreadable, or malformed CA bundle, so tls.X509KeyPool/AppendCertsFromPEM fails inside createHTTPClient.

Common situations: Typo or wrong key in the rootCA configmap/secret reference; CA bundle stored as non-PEM data; RBAC preventing argo-server from reading the referenced configmap/secret (often surfaced as the wrapped error).

Related errors


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