argoproj/argo-workflows · error

GCS client CredentialsFromJSONWithType: %w

Error message

GCS client CredentialsFromJSONWithType: %w

What it means

newGCSClientWithCredential parses the service-account JSON key into google.Credentials before building a storage.Client. This error wraps a failure from google.CredentialsFromJSONWithType, meaning the JSON key is not parseable or is not a service-account credential. The driver throws it so the misconfiguration is reported before any GCS API call is attempted.

Source

Thrown at workflow/artifacts/gcs/gcs.go:86

	}
	if e, ok := err.(interface{ Unwrap() error }); ok {
		return isTransientGCSErr(ctx, e.Unwrap())
	}
	return false
}

func (h *ArtifactDriver) newGCSClient(ctx context.Context) (*storage.Client, error) {
	if h.ServiceAccountKey != "" {
		return newGCSClientWithCredential(ctx, h.ServiceAccountKey)
	}
	// Assume it uses Workload Identity
	return newGCSClientDefault(ctx)
}

func newGCSClientWithCredential(ctx context.Context, serviceAccountJSON string) (*storage.Client, error) {
	creds, err := google.CredentialsFromJSONWithType(ctx, []byte(serviceAccountJSON), google.ServiceAccount, storage.ScopeReadWrite)
	if err != nil {
		return nil, fmt.Errorf("GCS client CredentialsFromJSONWithType: %w", err)
	}
	client, err := storage.NewClient(ctx, option.WithCredentials(creds))
	if err != nil {
		return nil, fmt.Errorf("GCS storage.NewClient with credential: %w", err)
	}
	return client, nil
}

func newGCSClientDefault(ctx context.Context) (*storage.Client, error) {
	client, err := storage.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("GCS storage.NewClient: %w", err)
	}
	return client, nil
}

// Load function downloads objects from GCS
func (h *ArtifactDriver) Load(ctx context.Context, inputArtifact *wfv1.Artifact, path string) error {

View on GitHub (pinned to 35bff19146)

Solutions

  1. Verify the secret contains a full service-account JSON key with "type": "service_account" (download via gcloud iam service-accounts keys create)
  2. Base64/escape the key correctly when creating the Kubernetes secret (kubectl create secret generic --from-file=..., not hand-inlined YAML)
  3. Ensure the artifact spec points at the right secret key name
  4. If not using a key at all, remove serviceAccountKeySecret so the driver falls back to newGCSClientDefault (workload identity/ADC)

Example fix

// before: key created from user credentials / invalid JSON
kubectl create secret generic gcs-creds --from-literal=serviceAccountKey='{bad json'
// after
gcloud iam service-accounts keys create key.json --iam-account=sa@project.iam.gserviceaccount.com
kubectl create secret generic gcs-creds --from-file=serviceAccountKey=key.json
Defensive patterns

Strategy: validation

Validate before calling

import "encoding/json"
func isValidServiceAccountKey(secretVal string) bool {
	var m map[string]any
	if err := json.Unmarshal([]byte(secretVal), &m); err != nil { return false }
	t, _ := m["type"].(string)
	_, hasPEM := m["private_key"]
	return t == "service_account" && hasPEM && m["client_email"] != nil
}

Try / catch

var argoerrors "github.com/argoproj/argo-workflows/v4/errors"
_, err := saveArtifact(ctx, art)
if err != nil {
	if strings.Contains(err.Error(), "CredentialsFromJSONWithType") {
		// bad/missing service-account key: fix secret and resubmit
	}
	return err
}

Prevention

When it happens

Trigger: Calling a GCS artifact Load/Save where the artifact's serviceAccountKeySecret contains a value that fails credentials parsing: invalid JSON, wrong key type (e.g. gcloud user credentials, API key, or a workload-identity federated config instead of type "service_account"), or empty string.

Common situations: Secret created from a gcloud user account JSON instead of a service-account key; secret truncated or with unescaped newlines in YAML; using an access token rather than a key; GCP project key rotated/deleted.

Related errors


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