iflytek/astron-agent · error · BusinessException

S3_UPLOAD_ERROR

S3_UPLOAD_ERROR

Error message

S3_UPLOAD_ERROR

What it means

uploadInternal wraps any exception from the S3/object-storage put into S3_UPLOAD_ERROR. After the workflow and file are validated, the artifact bytes are written to object storage; if that call fails (network error, bad credentials, bucket missing, size/quota rejection), the service translates the low-level SDK exception into this BusinessException and logs workflowId, uid, and fileName for diagnosis.

Solutions

  1. Check toolkit service logs for the wrapped 'Upload workflow artifact failed' stack trace to see the root SDK exception
  2. Verify S3/MinIO connectivity and credentials (endpoint, access key, secret, bucket) in the service configuration
  3. Confirm bucket exists and the service account has put-object permission; test with a direct SDK/mc upload
  4. Check proxy/load-balancer body-size limits and request timeouts for large files

Example fix

// before: misconfigured endpoint -> S3_UPLOAD_ERROR
s3.endpoint=http://internal-minio:9000  // host unreachable
// after
s3.endpoint=http://minio.minio.svc.cluster.local:9000
s3.access-key=<valid-key>
s3.secret-key=<valid-secret>
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight the object store before uploading
boolean ok = storageHealthCheck.ping(); // S3 headBucket or MinIO health endpoint
if (!ok) throw new IllegalStateException("Object storage unreachable, abort upload");

Try / catch

try {
    artifactApi.upload(workflowId, file);
} catch (BusinessException e) {
    if ("S3_UPLOAD_ERROR".equals(e.getCode())) {
        log.error("S3 upload failed; check storage config/health", e);
        throw new StorageUnavailableException(e); // surface infra issue, don't blindly retry
    }
    throw e;
}

Prevention

When it happens

Trigger: Object store unreachable or timing out during artifact upload; wrong S3 endpoint/credentials/bucket configuration; bucket quota or permission rejection; oversized multipart body dropped by a proxy before the SDK call.

Common situations: MinIO/S3 not running or misconfigured in the deployment environment; expired access keys; DNS or security-group changes breaking the storage endpoint; nginx client_max_body_size rejecting large artifacts.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/2c8a3f8b8b5ffd0a. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowArtifactService.java:317

        workflow = lockWorkflowForArtifactQuota(workflow.getId(), flowId, normalizedUid, spaceId);
        enforceWorkflowArtifactQuota(workflow.getId(), file.getSize());
        String objectKey = buildObjectKey(workflow.getId(), runId, validatedArtifact.fileName());
        try (InputStream input = file.getInputStream()) {
            s3ClientUtil.uploadObject(
                    artifactProperties.getArtifactBucket(),
                    objectKey,
                    validatedArtifact.contentType(),
                    input,
                    file.getSize(),
                    -1);
        } catch (Exception ex) {
            log.error(
                    "Upload workflow artifact failed, workflowId={}, uid={}, fileName={}",
                    workflow.getId(),
                    normalizedUid,
                    validatedArtifact.fileName(),
                    ex);
            throw new BusinessException(ResponseEnum.S3_UPLOAD_ERROR);
        }
        try {
            WorkflowArtifact artifact = new WorkflowArtifact();
            LocalDateTime now = LocalDateTime.now();
            artifact.setUid(normalizedUid);
            artifact.setSpaceId(workflow.getSpaceId());
            artifact.setWorkflowId(workflow.getId());
            artifact.setRunId(StringUtils.trimToEmpty(runId));
            artifact.setNodeId(StringUtils.trimToEmpty(nodeId));
            artifact.setSkillId(StringUtils.trimToEmpty(skillId));
            artifact.setFileName(validatedArtifact.fileName());
            artifact.setObjectKey(objectKey);
            artifact.setBucketName(artifactProperties.getArtifactBucket());
            artifact.setContentType(validatedArtifact.contentType());
            artifact.setFileSize(file.getSize());
            artifact.setSource(normalizeSource(source));
            artifact.setDeleted(Boolean.FALSE);
            artifact.setCreateTime(now);

View on GitHub (pinned to 5e758547a8)