flipped-aurora/gin-vue-admin · error

function client.DeleteObjects() failed, err:

Error message

function client.DeleteObjects() failed, err:

What it means

Wraps the error from the AWS SDK v2 client.DeleteObjects() (bulk delete via S3 RemoveObjects) in AwsS3.DeleteFiles. Unlike the single-key delete, this error means the whole batch API call itself failed (auth, permission, request too large, network) rather than individual keys failing; per-key failures are returned separately as []DeleteFailure via the out.Errors loop.

Source

Thrown at server/utils/upload/aws_s3.go:148

	objects := make([]types.ObjectIdentifier, 0, len(keys))
	for _, key := range keys {
		fullKey := key
		// 入参可能是短 key(不含前缀),也可能是 List 出来的全路径 key;统一拼接前缀时避免重复。
		if prefix != "" && !strings.HasPrefix(key, prefix+"/") {
			fullKey = prefix + "/" + key
		}
		objects = append(objects, types.ObjectIdentifier{Key: aws.String(fullKey)})
	}

	out, err := client.DeleteObjects(ctx, &s3.DeleteObjectsInput{
		Bucket: aws.String(bucket),
		Delete: &types.Delete{
			Objects: objects,
			Quiet:   aws.Bool(true),
		},
	})
	if err != nil {
		return nil, errors.New("function client.DeleteObjects() failed, err:" + err.Error())
	}

	for _, e := range out.Errors {
		key := ""
		if e.Key != nil {
			key = *e.Key
		}
		msg := "unknown error"
		if e.Message != nil {
			msg = *e.Message
		}
		failed = append(failed, DeleteFailure{Key: key, Err: errors.New(msg)})
	}
	return failed, nil
}

// ListFiles 按前缀列举存储对象,cursor 映射到 ContinuationToken。
func (*AwsS3) ListFiles(ctx context.Context, prefix, cursor string, limit int) (files []FileInfo, nextCursor string, hasMore bool, err error) {

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Grant s3:MultiObjectDelete / s3:DeleteObject permissions for batch deletes to the SDK credentials
  2. Chunk key lists into smaller batches (e.g. <=1000 keys, S3's hard limit) before calling DeleteObjects
  3. Check the appended err detail for the AWS error code and fix accordingly (AuthFailure, AccessDenied, networking)
  4. Retry the batch on transient network errors with exponential backoff; per-key failures will still come back as DeleteFailure entries

Example fix

// before
out, err := client.DeleteObjects(ctx, &s3.DeleteObjectsInput{Bucket: aws.String(bucket), Delete: &types.Delete{Objects: objects}}) // all keys at once
// after
for chunk := range slices.Chunk(objects, 1000) {
    out, err := client.DeleteObjects(ctx, &s3.DeleteObjectsInput{Bucket: aws.String(bucket), Delete: &types.Delete{Objects: chunk, Quiet: aws.Bool(true)}})
    if err != nil { return nil, fmt.Errorf("function client.DeleteObjects() failed, err:%w", err) }
}
Defensive patterns

Strategy: retry

Validate before calling

const maxBatch = 1000
if len(objects) == 0 { return nil, nil }
if len(objects) > maxBatch {
    return nil, fmt.Errorf("batch size %d exceeds S3 limit of %d", len(objects), maxBatch)
}
for _, o := range objects { if o.Key == nil || *o.Key == "" { return nil, errors.New("empty key in batch") } }

Try / catch

failed, err := s3Store.DeleteFiles(keys)
if err != nil {
    var ae smithy.APIError
    if errors.As(err, &ae) && isTransient(ae.ErrorCode()) {
        return retryWithBackoff(3, func() error { _, err = s3Store.DeleteFiles(keys); return err })
    }
    return err
}

Prevention

When it happens

Trigger: Calling DeleteFiles with a batch when: credentials lack s3:DeleteObjects/s3:DeleteObject on the batch, the request payload exceeds S3 limits, the endpoint is unreachable, or the SDK cannot marshal/execute the batch request at all.

Common situations: Batch deleting thousands of keys with a read-only role; MinIO/compatibility endpoints rejecting the multi-delete API; transient network outage during batch operations; oversized key lists pushed in one call.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/2030d7f5d6ef0489. Report an issue: GitHub.