flipped-aurora/gin-vue-admin · error

function bucketManager.Batch() failed, err:

Error message

function bucketManager.Batch() failed, err:

What it means

Wraps a fatal error from Qiniu's bucketManager.Batch() in DeleteFiles(). Batch deletes objects in bulk; the code only treats it as fatal when the batch result slice is empty (no per-key results at all).

Source

Thrown at server/utils/upload/qiniu.go:112

// DeleteFiles 批量删除对象,通过通用 Batch 接口,逐项检查 code(200/204 成功)。
func (*Qiniu) DeleteFiles(ctx context.Context, keys []string) ([]DeleteFailure, error) {
	if len(keys) == 0 {
		return nil, nil
	}

	bucket := global.GVA_CONFIG.Qiniu.Bucket
	operations := make([]string, 0, len(keys))
	for _, key := range keys {
		operations = append(operations, storage.URIDelete(bucket, key))
	}

	bucketManager := newBucketManager()
	ret, err := bucketManager.Batch(operations)
	if err != nil {
		// 部分 key 失败时 Batch 仍可能返回结果,这里仅当完全没有结果时视为致命错误。
		if len(ret) == 0 {
			logger.WithCtx(ctx).Mod("upload").Err(err).Error("function bucketManager.Batch() failed")
			return nil, errors.New("function bucketManager.Batch() failed, err:" + err.Error())
		}
		logger.WithCtx(ctx).Mod("upload").Err(err).Error("function bucketManager.Batch() partial failure")
	}

	failed := make([]DeleteFailure, 0)
	for i, op := range ret {
		// 200 / 204 视为删除成功
		if op.Code != http.StatusOK && op.Code != http.StatusNoContent {
			var key string
			if i < len(keys) {
				key = keys[i]
			}
			failed = append(failed, DeleteFailure{Key: key, Err: fmt.Errorf("delete failed, code: %d", op.Code)})
		}
	}
	return failed, nil
}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Inspect the wrapped err suffix for the underlying Qiniu error code
  2. Reduce batch size (split keys into smaller chunks, e.g. <=1000 per Batch)
  3. Re-check Qiniu AK/SK and bucket configuration
  4. Retry on transient network errors; per-key failures are returned via DeleteFailure, not this error

Example fix

// before
uploadQiniu.DeleteFiles(ctx, thousandsOfKeys) // one huge Batch may fail fatally
// after
for chunk := range slices.Chunk(keys, 500) {
    uploadQiniu.DeleteFiles(ctx, chunk)
}
Defensive patterns

Strategy: retry

Validate before calling

if len(keys) > 1000 {
    return fmt.Errorf("batch too large: %d keys", len(keys))
}

Try / catch

failed, err := q.DeleteFiles(ctx, keys)
if err != nil {
    if isTransient(err) {
        // retry with backoff
    }
    return err
}
// handle partial failures in `failed` slice separately

Prevention

When it happens

Trigger: Calling DeleteFiles(ctx, keys) when the Batch call fails entirely: auth failure, invalid bucket, oversized batch, or network error, with len(ret)==0.

Common situations: Expired/incorrect Qiniu credentials, batch containing too many keys for one request, bucket region mismatch, transient network outage.

Related errors


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