flipped-aurora/gin-vue-admin · error
function bucket.DeleteObjects() failed, err:
Error message
function bucket.DeleteObjects() failed, err:
What it means
Returned by AliyunOSS.DeleteFiles (server/utils/upload/aliyun_oss.go:109) when bucket.DeleteObjects(keys) — the OSS DeleteMultipleObjects API — fails after a valid bucket client was created. The request reached (or tried to reach) OSS and was rejected: causes include authentication, permission (oss:DeleteObject), request size limits, or network errors. Unlike the per-key comparison that follows, this error aborts the whole batch.
Source
Thrown at server/utils/upload/aliyun_oss.go:109
return exist, nil
}
// DeleteFiles 批量删除对象,对比入参与已删除列表,未删的收集为 DeleteFailure。
func (*AliyunOSS) DeleteFiles(ctx context.Context, keys []string) ([]DeleteFailure, error) {
if len(keys) == 0 {
return nil, nil
}
bucket, err := NewBucket()
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("function AliyunOSS.NewBucket() Failed")
return nil, errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error())
}
result, err := bucket.DeleteObjects(keys)
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("function bucket.DeleteObjects() failed")
return nil, errors.New("function bucket.DeleteObjects() failed, err:" + err.Error())
}
// 默认非 quiet 模式,OSS 会返回已删除的 key 列表,与之对比找出未删项。
deleted := make(map[string]struct{}, len(result.DeletedObjects))
for _, k := range result.DeletedObjects {
deleted[k] = struct{}{}
}
failed := make([]DeleteFailure, 0)
for _, key := range keys {
if _, ok := deleted[key]; !ok {
failed = append(failed, DeleteFailure{Key: key, Err: errors.New("对象未被删除")})
}
}
return failed, nil
}
// ListFiles 按前缀列举对象,cursor 映射为 OSS 的 marker。View on GitHub (pinned to 3136500ef3)
Solutions
- Chunk keys into batches of ≤1000 before calling DeleteObjects
- Grant the RAM user oss:DeleteObject on the bucket resources
- Read the wrapped err (oss.ServiceError) for the exact code: AccessDenied → permissions, SignatureDoesNotMatch → wrong secret, RequestTimeout → network
- Retry transient network errors with backoff; OSS batch delete is idempotent for already-deleted keys
Example fix
// before
result, err := bucket.DeleteObjects(keys)
if err != nil {
return nil, errors.New("function bucket.DeleteObjects() failed, err:" + err.Error())
}
// after: chunk to OSS limit of 1000 keys per call
const maxBatch = 1000
for i := 0; i < len(keys); i += maxBatch {
end := i + maxBatch
if end > len(keys) {
end = len(keys)
}
if _, err := bucket.DeleteObjects(keys[i:end]); err != nil {
return nil, fmt.Errorf("function bucket.DeleteObjects() failed: %w", err)
}
} Defensive patterns
Strategy: retry
Validate before calling
func chunkForOSS(keys []string, size int) [][]string {
if size <= 0 || size > 1000 {
size = 1000
}
var batches [][]string
for i := 0; i < len(keys); i += size {
end := i + size
if end > len(keys) {
end = len(keys)
}
batches = append(batches, keys[i:end])
}
return batches
} Type guard
func isRetryableOSSErr(err error) bool {
var se oss.ServiceError
if !errors.As(err, &se) {
return true // network-level errors are usually retryable
}
return se.StatusCode == 429 || se.StatusCode >= 500 || se.Code == "RequestTimeout"
} Try / catch
for _, batch := range chunkForOSS(keys, 1000) {
err := retryWithBackoff(3, func() error {
_, err := bucket.DeleteObjects(batch)
return err
})
if err != nil {
if se, ok := isOSSServiceError(err); ok && se.StatusCode == 403 {
return fmt.Errorf("permission denied deleting objects (check oss:DeleteObject): %w", err)
}
return fmt.Errorf("batch delete failed: %w", err)
}
} Prevention
- Never send more than 1000 keys per DeleteObjects call — chunk always
- Ensure the RAM policy includes oss:DeleteObject for the bucket/objects
- Retry with exponential backoff on 5xx/timeouts; OSS batch delete is safe to retry
- Keep batch delete idempotent: deleted-again keys still count as success
When it happens
Trigger: Calling DeleteFiles with >1000 keys (OSS hard limit per DeleteMultipleObjects call), RAM user without oss:DeleteObject permission, expired/invalid credentials, network failure mid-request, or keys with invalid characters that violate OSS key constraints.
Common situations: Bulk cleanup jobs deleting thousands of objects in one call, restricted IAM policies granting only read/upload, key rotation between request signing and execution, batch sizes not chunked before reaching this wrapper.
Related errors
- function bucket.IsObjectExist() failed, err:
- 对象未被删除
- function bucket.ListObjects() failed, err:
- function client.DeleteObjects() failed, err:
- unknown error
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/92f99c9d4d67ee74.
Report an issue: GitHub.