flipped-aurora/gin-vue-admin · warning
unknown error
Error message
unknown error
What it means
Within DeleteFiles, per-key failures returned in the DeleteObjects response (out.Errors) are converted into DeleteFailure entries. When the service omits the Message pointer (nil), the code substitutes the placeholder 'unknown error'. This is not a transport failure — the batch succeeded but some individual keys could not be deleted and R2 did not explain why.
Source
Thrown at server/utils/upload/cloudflare_r2.go:145
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 (c *CloudflareR2) ListFiles(ctx context.Context, prefix, cursor string, limit int) (files []FileInfo, nextCursor string, hasMore bool, err error) {
client, err := c.newR2Client()
if err != nil {
return nil, "", false, err
}
bucket := global.GVA_CONFIG.CloudflareR2.Bucket
if limit <= 0 {
limit = 100
}
input := &s3.ListObjectsV2Input{
Bucket: aws.String(bucket),View on GitHub (pinned to 3136500ef3)
Solutions
- Treat the DeleteFailure entry by Key: re-attempt a single DeleteObject for that key to obtain a concrete error
- Log the raw DeleteObjects response Errors array to see Code/Key even when Message is nil
- Sanitize key names (no leading '/', control chars, over-length) before batch delete
- Check for object lock/retention settings on the bucket blocking deletion
- Report to Cloudflare support if R2 consistently returns empty error messages for valid keys
Example fix
// before
msg := "unknown error"
if e.Message != nil { msg = *e.Message }
// after
msg := "unknown error"
if e.Message != nil { msg = *e.Message }
if e.Code != nil { msg = *e.Code + ": " + msg } Defensive patterns
Strategy: type-guard
Validate before calling
// before batch delete, confirm each key exists and is deletable
for _, k := range keys {
if _, err := uploader.Exists(ctx, k); err != nil {
return fmt.Errorf("cannot verify key %s: %w", k, err)
}
} Type guard
func describeFailure(e types.Error) string {
var key, msg, code string
if e.Key != nil { key = *e.Key }
if e.Message != nil { msg = *e.Message } else { msg = "unknown error" }
if e.Code != nil { code = *e.Code }
return fmt.Sprintf("key=%s code=%s msg=%s", key, code, msg)
} Try / catch
failed, err := uploader.DeleteFiles(ctx, keys)
if err != nil { return err }
for _, f := range failed {
logger.Warn("per-key delete failure", zap.String("key", f.Key), zap.String("detail", f.Err.Error()))
// re-attempt single delete to obtain a concrete error
if derr := uploader.DeleteFile(ctx, f.Key); derr != nil {
logger.Error("single delete also failed", zap.String("key", f.Key), zap.Error(derr))
}
} Prevention
- Always inspect every DeleteFailure entry; don't ignore partial failures
- Re-run failed keys as single deletes to surface the real error
- Sanitize key names to avoid R2-side rejections with empty messages
- Check object lock/retention policies on buckets with partial failures
When it happens
Trigger: DeleteObjects batch partially fails and R2 returns an error entry with a nil Message and/or nil Key — typically for keys rejected at a lower level (invalid key encoding, lock/retention conflicts) where the S3-compatible layer doesn't populate the message field.
Common situations: Keys containing characters R2 rejects, objects under retention/legal hold, keys that were listed but vanished mid-batch with an unpopulated error entry, S3-compatible layer differences between AWS and R2 response population.
Related errors
- function client.DeleteObjects() failed, err:
- unknown error
- function client.DeleteObject() failed, err:
- function client.ListObjectsV2() failed, err:
- function bucket.DeleteObjects() failed, err:
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/12533d30df12528b.
Report an issue: GitHub.