{"record":{"id":"a8dd0f445e28f875","repo":"argoproj/argo-workflows","slug":"gcs-client-credentialsfromjsonwithtype-w","errorCode":null,"errorMessage":"GCS client CredentialsFromJSONWithType: %w","messagePattern":"GCS client CredentialsFromJSONWithType: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/gcs/gcs.go","lineNumber":86,"sourceCode":"\t}\n\tif e, ok := err.(interface{ Unwrap() error }); ok {\n\t\treturn isTransientGCSErr(ctx, e.Unwrap())\n\t}\n\treturn false\n}\n\nfunc (h *ArtifactDriver) newGCSClient(ctx context.Context) (*storage.Client, error) {\n\tif h.ServiceAccountKey != \"\" {\n\t\treturn newGCSClientWithCredential(ctx, h.ServiceAccountKey)\n\t}\n\t// Assume it uses Workload Identity\n\treturn newGCSClientDefault(ctx)\n}\n\nfunc newGCSClientWithCredential(ctx context.Context, serviceAccountJSON string) (*storage.Client, error) {\n\tcreds, err := google.CredentialsFromJSONWithType(ctx, []byte(serviceAccountJSON), google.ServiceAccount, storage.ScopeReadWrite)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GCS client CredentialsFromJSONWithType: %w\", err)\n\t}\n\tclient, err := storage.NewClient(ctx, option.WithCredentials(creds))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GCS storage.NewClient with credential: %w\", err)\n\t}\n\treturn client, nil\n}\n\nfunc newGCSClientDefault(ctx context.Context) (*storage.Client, error) {\n\tclient, err := storage.NewClient(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GCS storage.NewClient: %w\", err)\n\t}\n\treturn client, nil\n}\n\n// Load function downloads objects from GCS\nfunc (h *ArtifactDriver) Load(ctx context.Context, inputArtifact *wfv1.Artifact, path string) error {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/gcs/gcs.go#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the secret contains a full service-account JSON key with \"type\": \"service_account\" (download via gcloud iam service-accounts keys create)","Base64/escape the key correctly when creating the Kubernetes secret (kubectl create secret generic --from-file=..., not hand-inlined YAML)","Ensure the artifact spec points at the right secret key name","If not using a key at all, remove serviceAccountKeySecret so the driver falls back to newGCSClientDefault (workload identity/ADC)"],"exampleFix":"// before: key created from user credentials / invalid JSON\nkubectl create secret generic gcs-creds --from-literal=serviceAccountKey='{bad json'\n// after\ngcloud iam service-accounts keys create key.json --iam-account=sa@project.iam.gserviceaccount.com\nkubectl create secret generic gcs-creds --from-file=serviceAccountKey=key.json","handlingStrategy":"validation","validationCode":"import \"encoding/json\"\nfunc isValidServiceAccountKey(secretVal string) bool {\n\tvar m map[string]any\n\tif err := json.Unmarshal([]byte(secretVal), &m); err != nil { return false }\n\tt, _ := m[\"type\"].(string)\n\t_, hasPEM := m[\"private_key\"]\n\treturn t == \"service_account\" && hasPEM && m[\"client_email\"] != nil\n}","typeGuard":null,"tryCatchPattern":"var argoerrors \"github.com/argoproj/argo-workflows/v4/errors\"\n_, err := saveArtifact(ctx, art)\nif err != nil {\n\tif strings.Contains(err.Error(), \"CredentialsFromJSONWithType\") {\n\t\t// bad/missing service-account key: fix secret and resubmit\n\t}\n\treturn err\n}","preventionTips":["Create secrets with kubectl create secret --from-file, never hand-inlined YAML","Verify keys with `gcloud auth activate-service-account --key-file=key.json` before uploading","Prefer workload identity over JSON keys to avoid key management entirely"],"tags":["gcs","gcp","credentials","authentication"],"backgroundTag":"invalid-service-account-credentials","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}