hashicorp/terraform · error
bucket not exists
Error message
bucket %s not exists
What it means
Returned by getBucket() when the COS SDK returns a nil response pointer from Bucket.Get (list). On the list path the backend interprets a nil response as 'bucket not exists', which is an imperfect mapping — the real cause may be transport failure rather than absence.
Solutions
- Look at DEBUG line `getBucket <bucket>/<prefix>: error:` for the underlying SDK error.
- Confirm the bucket name includes the APPID suffix and the region matches.
- Grant `cos:GetBucket` (list) permission to the principal.
- Verify network reachability to COS and retry.
Example fix
// before: bucket name without APPID
backend "cos" { bucket="tf-state"; region="ap-guangzhou" }
// after: append APPID
backend "cos" { bucket="tf-state-1250000000"; region="ap-guangzhou" } Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: validate the bucket name (with APPID) and list permission
func bucketAccessible(ctx context.Context, client *cos.Client, bucket string) error {
_, rsp, err := client.Bucket.Get(ctx, &cos.BucketGetOptions{Prefix: ""})
if rsp == nil { return fmt.Errorf("could not reach COS for bucket %s: %w", bucket, err) }
defer rsp.Body.Close()
if rsp.StatusCode == 404 { return fmt.Errorf("bucket %s not found (check name-APPID and region)", bucket) }
if rsp.StatusCode == 403 { return fmt.Errorf("principal lacks cos:GetBucket on %s", bucket) }
return nil
} Type guard
func looksLikeCOSBucketName(name string) bool {
// <3-63 chars, lowercase, digits, hyphen>, ends with -<10 digit APPID>
matched, _ := regexp.MatchString(`^[a-z0-9-]{3,63}-[0-9]{10}$`, name)
return matched
} Try / catch
// Distinguish 404 (genuine absence) from nil-response (transport)
if rsp == nil { /* transport: retry */ } else if rsp.StatusCode == 404 { /* real absence: fix config */ } Prevention
- Always include the APPID suffix in the COS bucket name.
- Match the backend `region` to the bucket's actual region.
- Grant `cos:GetBucket` to the principal.
- Validate outbound connectivity before `terraform init`.
When it happens
Trigger: c.cosClient.Bucket.Get(...) returns (nil, rsp, err). Network failure, invalid endpoint, bad credentials, or the bucket genuinely being unreachable all collapse into this single message.
Common situations: Wrong `region` for the bucket name; APPID not embedded in the bucket name (`<bucket>-<appid>`); credentials lack `cos:GetBucket`; no outbound connectivity; transient DNS failure.
Related errors
- failed to create bucket
- failed to delete bucket
- failed to empty bucket
- failed to create tag
- failed to delete file
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a314ea14555c5e4f.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/cos/client.go:285
log.Printf("[DEBUG] deleteObject %s: code: %d, error: %v", cosFile, rsp.StatusCode, err)
if rsp.StatusCode == 404 {
return nil
}
if err != nil {
return fmt.Errorf("failed to delete file %v: %v", cosFile, err)
}
return nil
}
// getBucket list bucket by prefix
func (c *remoteClient) getBucket(prefix string) (obs []cos.Object, err error) {
fs, rsp, err := c.cosClient.Bucket.Get(c.cosContext, &cos.BucketGetOptions{Prefix: prefix})
if rsp == nil {
log.Printf("[DEBUG] getBucket %s/%s: error: %v", c.bucket, prefix, err)
err = fmt.Errorf("bucket %s not exists", c.bucket)
return
}
defer rsp.Body.Close()
log.Printf("[DEBUG] getBucket %s/%s: code: %d, error: %v", c.bucket, prefix, rsp.StatusCode, err)
if rsp.StatusCode == 404 {
err = fmt.Errorf("bucket %s not exists", c.bucket)
return
}
if err != nil {
return
}
return fs.Contents, nil
}
// putBucket create cos bucketView on GitHub (pinned to d32a084675)