iflytek/astron-agent · critical · BusinessException

INTERNAL_SERVER_ERROR

INTERNAL_SERVER_ERROR

Error message

INTERNAL_SERVER_ERROR

What it means

S3ClientUtil.init ensures the configured S3/MinIO bucket exists and is correctly configured (create, privacy policy). When any S3 SDK operation fails (bucket check/create/policy, or XML parsing of the response), the error is logged with errorType/errorCode and rethrown as a generic BusinessException(INTERNAL_SERVER_ERROR) — the real cause is only in the server log.

Solutions

  1. Check the service log line 'Failed to check/create/configure S3 bucket' for the underlying errorType/errorCode
  2. Verify S3 endpoint, accessKey, secretKey and bucket config (env/properties) and that MinIO is reachable (curl the endpoint)
  3. Confirm credentials have s3:CreateBucket/PutBucketPolicy permissions, or pre-create the bucket
  4. Retry startup after fixing infra; the util intentionally maps all SDK failures to INTERNAL_SERVER_ERROR

Example fix

// before
# application.yml
s3.endpoint: http://minio:9001  # wrong port, connection fails at init
// after
s3.endpoint: http://minio:9000  # match the actual MinIO API port
Defensive patterns

Strategy: try-catch

Validate before calling

boolean cfgOk = endpoint != null && !endpoint.isBlank() && accessKey != null && secretKey != null && defaultBucket != null;
boolean reachable = cfgOk && java.net.InetAddress.getByName(java.net.URI.create(endpoint).getHost()).isReachable(3000);

Try / catch

try { s3ClientUtil.init(); } catch (BusinessException e) { log.error("S3 init failed — check endpoint/credentials/bucket and server log for errorType/errorCode", e); throw new IllegalStateException("Object storage unavailable", e); }

Prevention

When it happens

Trigger: Bean initialization against an unreachable endpoint, wrong credentials, a missing bucket the client cannot create, a policy document MinIO rejects, or a malformed XML response (XmlParserException).

Common situations: MinIO/S3 not started or wrong endpoint/port in docker-compose; incorrect access/secret keys; bucket name conflicts or insufficient permissions; MinIO version rejecting the enforced privacy policy; network/DNS issues between services.

Related errors


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

Appendix: source

Thrown at console/backend/commons/src/main/java/com/iflytek/astron/console/commons/util/S3ClientUtil.java:139

                    if (!isConcurrentBucketCreation(exception)) {
                        throw exception;
                    }
                    log.info("S3 bucket was created concurrently: {}", defaultBucket);
                }
            } else {
                log.info("S3 bucket already exists: {}", defaultBucket);
            }

            reconcileBucketPolicy(defaultBucket, enablePublicRead);
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException
                | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException
                | XmlParserException e) {
            log.error(
                    "Failed to check/create/configure S3 bucket '{}' (errorType={}, errorCode={})",
                    defaultBucket,
                    exceptionType(e),
                    safeS3ErrorCode(e));
            throw new BusinessException(ResponseEnum.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * Validate required configuration parameters.
     */
    private void validateConfiguration() {
        if (endpoint == null || endpoint.trim().isEmpty()) {
            log.error("S3 endpoint is not configured");
            throw new BusinessException(ResponseEnum.INTERNAL_SERVER_ERROR);
        }
        if (remoteEndpoint == null || remoteEndpoint.trim().isEmpty()) {
            log.error("S3 remoteEndpoint is not configured");
            throw new BusinessException(ResponseEnum.INTERNAL_SERVER_ERROR);
        }
        if (accessKey == null
                || accessKey.trim().isEmpty()
                || LEGACY_PLACEHOLDER_ACCESS_KEY.equals(accessKey.trim())) {

View on GitHub (pinned to 5e758547a8)