flipped-aurora/gin-vue-admin · error

delete failed, code: %d

Error message

delete failed, code: %d

What it means

The Qiniu DeleteFiles implementation batch-deletes keys and treats HTTP 200/204 as success. Any operation returning another status code produces a DeleteFailure with "delete failed, code: %d". Note the key may be empty when the response index exceeds the keys slice, so correlate by position carefully.

Source

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

	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
}

// ListFiles 按前缀列举对象,cursor 映射为七牛的 marker。
func (*Qiniu) ListFiles(ctx context.Context, prefix, cursor string, limit int) ([]FileInfo, string, bool, error) {
	if limit <= 0 {
		limit = 100
	}

	bucketManager := newBucketManager()
	entries, _, nextMarker, hasNext, err := bucketManager.ListFiles(global.GVA_CONFIG.Qiniu.Bucket, prefix, "", cursor, limit)
	if err != nil {
		logger.WithCtx(ctx).Mod("upload").Err(err).Error("function bucketManager.ListFiles() failed")
		return nil, "", false, errors.New("function bucketManager.ListFiles() failed, err:" + err.Error())
	}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Check the returned op.Code against Qiniu's status code table (612 = file not found is usually harmless).
  2. Verify qiniu AccessKey/SecretKey and bucket configuration are valid and not expired.
  3. Treat 612 (no such file) as success in caller logic if idempotent deletes are desired.
  4. Retry the failed keys individually; other keys in the batch may have succeeded.

Example fix

// before
failed, _ := uploader.DeleteFiles(ctx, keys)

// after
failed, err := uploader.DeleteFiles(ctx, keys)
for _, f := range failed {
    if !strings.Contains(f.Err.Error(), "code: 612") { // ignore already-deleted
        log.Printf("delete %s failed: %v", f.Key, f.Err)
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if len(keys) == 0 {
    return nil // nothing to delete
}
for _, k := range keys {
    if strings.TrimSpace(k) == "" {
        return errors.New("empty key in qiniu batch delete")
    }
}

Try / catch

failed, err := uploader.DeleteFiles(ctx, keys)
if err != nil {
    return err
}
for _, f := range failed {
    if strings.Contains(f.Err.Error(), "code: 612") {
        continue // file already gone; treat as success
    }
    log.Printf("qiniu delete failed: key=%s err=%v", f.Key, f.Err)
}

Prevention

When it happens

Trigger: Calling DeleteFiles on the qiniu uploader when an op.Code is neither 200 nor 204 — e.g. 631 (bucket not found), 612 (no such file), or 401/403 auth failures from Qiniu's batch API.

Common situations: Expired or wrong AccessKey/Secret; deleting keys already removed (612); bucket name mismatch between config and request; Qiniu status codes outside the standard 200/204 set used here.

Related errors


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