{"record":{"id":"8a75095323b5ea0d","repo":"iflytek/astron-agent","slug":"s3-presign-error","errorCode":"S3_PRESIGN_ERROR","errorMessage":"S3 presign error","messagePattern":"S3 presign error","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/commons/src/main/java/com/iflytek/astron/console/commons/util/S3ClientUtil.java","lineNumber":923,"sourceCode":"                    targetObjectKey,\n                    exceptionType(exception));\n            return false;\n        }\n    }\n\n    /**\n     * Generate a presigned PUT URL for browser direct upload.\n     *\n     * @param bucketName target bucket\n     * @param objectKey object key\n     * @param expirySeconds expiry in seconds (MinIO requires 1..604800)\n     * @return URL usable for HTTP PUT\n     */\n    public String generatePresignedPutUrl(String bucketName, String objectKey, int expirySeconds) {\n        // Validate parameters\n        if (bucketName == null || bucketName.trim().isEmpty()) {\n            log.error(\"Bucket name cannot be null or empty\");\n            throw new BusinessException(ResponseEnum.S3_PRESIGN_ERROR);\n        }\n        if (objectKey == null || objectKey.trim().isEmpty()) {\n            log.error(\"Object key cannot be null or empty\");\n            throw new BusinessException(ResponseEnum.S3_PRESIGN_ERROR);\n        }\n        if (expirySeconds < 1 || expirySeconds > 604800) {\n            log.error(\"Expiry seconds must be between 1 and 604800, got: {}\", expirySeconds);\n            throw new BusinessException(ResponseEnum.S3_PRESIGN_ERROR);\n        }\n\n        try {\n            return presignClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()\n                    .method(Method.PUT)\n                    .bucket(bucketName)\n                    .object(objectKey)\n                    .expiry(expirySeconds)\n                    .build());\n        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException","sourceCodeStart":905,"sourceCodeEnd":941,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/commons/src/main/java/com/iflytek/astron/console/commons/util/S3ClientUtil.java#L905-L941","documentation":"generatePresignedPutUrl validates the bucketName parameter before contacting S3 and throws BusinessException(S3_PRESIGN_ERROR) when it is null or blank. This is a client-side argument validation; no presign request is made.","triggerScenarios":"Calling generatePresignedPutUrl(null, objectKey, expiry) or with a bucketName that is empty or whitespace-only, usually from an unset configuration property.","commonSituations":"S3 bucket name missing from application.yml/env, a null value propagated from tenant/space config, or typo'd configuration key so the field defaults to null.","solutions":["Pass a non-empty bucket name at the call site","Check the bucket configuration property is set in application config / environment","Add startup validation that fails fast when the bucket config is missing"],"exampleFix":"// before\nString url = s3ClientUtil.generatePresignedPutUrl(config.getBucket(), key, 3600);\n// after\nString bucket = config.getBucket();\nif (bucket == null || bucket.trim().isEmpty()) {\n    throw new IllegalStateException(\"S3 bucket name is not configured\");\n}\nString url = s3ClientUtil.generatePresignedPutUrl(bucket, key, 3600);","handlingStrategy":"validation","validationCode":"if (bucketName == null || bucketName.trim().isEmpty()) {\n    throw new IllegalStateException(\"S3 bucket name must be configured\");\n}","typeGuard":"static boolean hasText(String s) { return s != null && !s.trim().isEmpty(); }","tryCatchPattern":"try {\n    return s3ClientUtil.generatePresignedPutUrl(bucket, key, expiry);\n} catch (BusinessException e) {\n    log.error(\"presign rejected: check bucket configuration\", e);\n    throw e;\n}","preventionTips":["Bind and assert S3 bucket config at application startup","Use a single config accessor for the bucket so nulls surface in one place","Add integration tests that fail when bucket config is missing"],"tags":["s3","presign","validation","config"],"backgroundTag":"empty-required-field","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}