{"record":{"id":"aed191a1f18a6b6d","repo":"argoproj/argo-workflows","slug":"failed-to-save-artifact-v","errorCode":null,"errorMessage":"Failed to save artifact: %v","messagePattern":"Failed to save artifact: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/artifacts/artifact_server.go","lineNumber":267,"sourceCode":"\t\treturn\n\t}\n\n\ta.logger.WithFields(logging.Fields{\n\t\t\"originalKey\": originalKey,\n\t\t\"newKey\":      newKey,\n\t}).Info(ctx, \"Uploading artifact with new key\")\n\n\t// Get the driver for the artifact\n\tkubeClient := auth.GetKubeClient(ctx)\n\tdriver, err := a.artDriverFactory(ctx, outputArtifact, resources{kubeClient, namespace})\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to create artifact driver: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\t// Upload using SaveStream\n\tif err := driver.SaveStream(ctx, file, outputArtifact); err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to save artifact: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\ta.logger.WithFields(logging.Fields{\n\t\t\"artifactName\": artifactName,\n\t\t\"key\":          newKey,\n\t}).Info(ctx, \"Successfully uploaded artifact\")\n\n\t// Return only name/key. The resolved ArtifactLocation contains bucket\n\t// endpoints and Secret selector names that the client does not need.\n\tresponse := map[string]any{\n\t\t\"name\": artifactName,\n\t\t\"key\":  newKey,\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tw.WriteHeader(http.StatusOK)\n\tif err := json.NewEncoder(w).Encode(response); err != nil {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/artifacts/artifact_server.go#L249-L285","documentation":"After the driver is created, the file stream is written to storage with driver.SaveStream(ctx, file, outputArtifact). Any storage-side failure — network errors, authentication rejection, bucket missing, quota exceeded, context cancellation — is surfaced as HTTP 500 \"Failed to save artifact: ...\" with the underlying driver error appended.","triggerScenarios":"Storage endpoint unreachable (wrong endpoint/region, DNS failure, firewall); bucket does not exist or the credentials lack write permission; object size exceeds limits or upload times out; the request context is canceled mid-upload (client disconnect); S3 signature/credential errors at write time.","commonSituations":"MinIO/S3 endpoint misconfigured (http vs https, wrong port); IAM/service account without putObject permission; bucket name typo; large uploads cut off by proxies with short idle timeouts; expired cloud credentials.","solutions":["Read the detailed driver error appended to the response; fix the indicated storage issue (bucket, permissions, endpoint).","Verify the bucket exists and credentials have write access (e.g. s3:PutObject).","Test connectivity from the argo-server pod to the storage endpoint (DNS, TLS, firewall).","For large files, check proxy/body-size/timeout settings including ARGO_SERVER_MAX_ARTIFACT_UPLOAD_BYTES.","Retry the upload once transient network issues are resolved."],"exampleFix":"// before (endpoint misconfigured)\ns3:\n  endpoint: my-minio:900\n// after\ns3:\n  endpoint: my-minio:9000\n  insecure: true","handlingStrategy":"retry","validationCode":"# Pre-flight: bucket reachable and writable from your network\nkubectl -n argo run --rm -i test-s3 --image=minio/mc -- \\\n  sh -c 'mc alias set t $ENDPOINT $KEY $SECRET && mc ls t/$BUCKET'","typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try { return await uploadArtifact(file); }\n  catch (e) {\n    if (e.status === 500 && e.body.includes('Failed to save artifact') && isTransient(e)) {\n      await sleep(backoff(attempt)); continue;\n    }\n    throw e;\n  }\n}","preventionTips":["Verify endpoint scheme/port (http vs https, correct MinIO port) before first upload.","Grant storage write permissions (e.g. s3:PutObject) to the credentials in use.","Keep uploads under ARGO_SERVER_MAX_ARTIFACT_UPLOAD_BYTES and proxy body limits.","Increase proxy idle timeouts for large uploads; monitor storage quota.","Rotate cloud credentials before expiry in long-lived installs."],"tags":["artifacts","storage","s3","network","internal-error"],"backgroundTag":"artifact-save-failed","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"}