flipped-aurora/gin-vue-admin · error
obs delete %s failed: code=%s, message=%s
Error message
obs delete %s failed: code=%s, message=%s
What it means
The Huawei OBS DeleteFiles implementation performs a batch delete; the OBS response can carry per-object Errors even when the overall call succeeds. For each failed entry a DeleteFailure is returned with "obs delete %s failed: code=%s, message=%s" including the key, OBS error code, and message. It surfaces partial batch-delete failures instead of silently dropping them.
Source
Thrown at server/utils/upload/obs.go:134
for _, k := range keys {
objects = append(objects, obs.ObjectToDelete{Key: k})
}
output, err := client.DeleteObjects(&obs.DeleteObjectsInput{
Bucket: global.GVA_CONFIG.HuaWeiObs.Bucket,
Objects: objects,
Quiet: true,
})
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("obs DeleteObjects 失败")
return nil, err
}
if output != nil {
for _, e := range output.Errors {
failed = append(failed, DeleteFailure{
Key: e.Key,
Err: fmt.Errorf("obs delete %s failed: code=%s, message=%s", e.Key, e.Code, e.Message),
})
}
}
return failed, nil
}
// ListFiles 按前缀列举对象,marker 分页:Marker=cursor,NextMarker→nextCursor,IsTruncated→hasMore。
func (o *Obs) ListFiles(ctx context.Context, prefix, cursor string, limit int) (files []FileInfo, nextCursor string, hasMore bool, err error) {
if limit <= 0 {
limit = 100
}
client, err := NewHuaWeiObsClient()
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("获取华为对象存储对象失败")
return nil, "", false, pkgerrors.Wrap(err, "获取华为对象存储对象失败!")
}
View on GitHub (pinned to 3136500ef3)
Solutions
- Read the code= and message= fields per DeleteFailure to identify the OBS error and the affected key.
- Verify the access key has OBS delete permission (IAM policy) for the bucket.
- Retry deleting only the failed keys after fixing permissions or confirming the objects' existence.
- Handle per-key failures individually — other keys in the batch may have succeeded.
Example fix
// before
failed, _ := uploader.DeleteFiles(ctx, keys) // ignores per-key failures
// after
failed, err := uploader.DeleteFiles(ctx, keys)
for _, f := range failed {
log.Printf("retry delete %s: %v", f.Key, f.Err)
_ = retryDelete(ctx, uploader, f.Key)
} Defensive patterns
Strategy: try-catch
Validate before calling
// best effort: check keys exist / are deletable before batch delete
for _, key := range keys {
if key == "" || strings.HasPrefix(key, "/") {
return fmt.Errorf("invalid key for OBS delete: %q", key)
}
} Try / catch
failed, err := uploader.DeleteFiles(ctx, keys)
if err != nil {
return err
}
for _, f := range failed {
var delErr *upload.DeleteFailure
log.Printf("obs delete failed key=%s: %v", f.Key, f.Err)
// inspect code= in f.Err to decide retry vs skip
} Prevention
- Grant IAM delete permissions for the bucket to the access key
- Treat batch delete as partial: always inspect the failed list
- Log per-key failures for later reconciliation
- Pre-validate key names before batch operations
When it happens
Trigger: Calling DeleteFiles on the OBS uploader where output.Errors is non-empty — e.g. deleting keys that don't exist with a policy that errors, insufficient IAM permissions, or keys locked/protected in the bucket.
Common situations: Wrong bucket/credentials with limited delete rights; objects already deleted by another process; OBS-specific error codes like AccessDenied or InvalidArgument in the multi-delete response.
Related errors
- delete failed, code: %d
- function bucketManager.Delete() failed, err:
- function bucketManager.Delete() failed, err:
- cos delete %s failed: code=%s, message=%s
- function client.DeleteObject() failed, err:
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/030523a55f1eea1d.
Report an issue: GitHub.