flipped-aurora/gin-vue-admin · error
function client.Object.Head() failed, err:
Error message
function client.Object.Head() failed, err:
What it means
Wraps a non-404 error from the COS SDK's client.Object.Head() in TencentCOS.Exists(). Head fetches object metadata to test existence; cos.IsNotFoundError results are converted to (false, nil), everything else is re-wrapped with this prefix.
Source
Thrown at server/utils/upload/tencent_cos.go:61
_, err := client.Object.Delete(context.Background(), name)
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("function bucketManager.Delete() failed")
return errors.New("function bucketManager.Delete() failed, err:" + err.Error())
}
return nil
}
// Exists 通过 Object.Head 检查对象是否存在;404 统一降级为 (false, nil)。
func (*TencentCOS) Exists(ctx context.Context, key string) (bool, error) {
client := NewClient()
name := global.GVA_CONFIG.TencentCOS.PathPrefix + "/" + key
_, err := client.Object.Head(ctx, name, nil)
if err != nil {
if cos.IsNotFoundError(err) {
return false, nil
}
logger.WithCtx(ctx).Mod("upload").Err(err).Error("function client.Object.Head() failed")
return false, errors.New("function client.Object.Head() failed, err:" + err.Error())
}
return true, nil
}
// DeleteFiles 批量删除:Object.DeleteMulti 一次提交,返回 Errors 逐个失败项。
// PathPrefix 拼接方式与 DeleteFile 一致。
func (*TencentCOS) DeleteFiles(ctx context.Context, keys []string) (failed []DeleteFailure, err error) {
client := NewClient()
objects := make([]cos.Object, 0, len(keys))
for _, k := range keys {
objects = append(objects, cos.Object{Key: global.GVA_CONFIG.TencentCOS.PathPrefix + "/" + k})
}
res, _, err := client.Object.DeleteMulti(ctx, &cos.ObjectDeleteMultiOptions{
Objects: objects,
Quiet: true,
})
if err != nil {View on GitHub (pinned to 3136500ef3)
Solutions
- Check the wrapped err suffix for the COS error code
- Ensure CAM grants cos:HeadObject/GetObject for the key
- Verify Bucket and Region config so the correct endpoint is used
- If you expect 404, note it is already handled — only non-404 failures reach this error
Example fix
// before
ok, err := cos.Exists(ctx, key) // 403 AccessDenied surfaces as wrapped Head error
// after
if err != nil && strings.Contains(err.Error(), "AccessDenied") {
return fmt.Errorf("check CAM permissions for cos:HeadObject: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
cfg := global.GVA_CONFIG.TencentCOS
if cfg.Bucket == "" || cfg.Region == "" {
return errors.New("cos bucket/region not configured")
} Try / catch
ok, err := cos.Exists(ctx, key)
if err != nil {
// 404 already mapped to (false, nil); here it's auth/network/permission
if strings.Contains(err.Error(), "AccessDenied") {
// fix CAM cos:HeadObject permission
}
return false, err
} Prevention
- Grant cos:HeadObject/GetObject permissions
- Validate bucket/region config at startup
- Do not conflate not-found (false,nil) with real failures
When it happens
Trigger: Calling Exists(ctx, key) when Object.Head fails for reasons other than not-found: auth failure, permission denied, network error, or malformed key.
Common situations: Invalid/expired Tencent COS credentials, CAM policy missing cos:GetObject/HeadObject, bucket region mismatch causing endpoint errors, VPC networking issues.
Related errors
- function bucketManager.Delete() failed, err:
- function client.Object.Put() failed, err:
- function client.Object.DeleteMulti() failed, err:
- function client.Bucket.Get() 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/a23cd6d49f74fecf.
Report an issue: GitHub.