hashicorp/terraform · error
S3 bucket does not exist. The referenced S3 bucket must…
Error message
S3 bucket %q does not exist. The referenced S3 bucket must have been previously created. If the S3 bucket was created within the last minute, please wait for a minute or two and try again. Error: %s
What it means
Thrown by Backend.Workspaces in the S3 state backend when ListObjectsV2 paginator's NextPage returns an error that IsA[*s3types.NoSuchBucket] matches. The errS3NoSuchBucket template explains the bucket must have been pre-created and that very-recent creation may need a minute to propagate. This is a config/existence failure, not transient.
Solutions
- Verify the bucket exists: `aws s3api head-bucket --bucket <name>` with the same credentials/profile OpenTofu uses.
- Check the `region` in the backend block matches the bucket's region.
- Confirm the AWS profile/role assumed by OpenTofu is the one that owns the bucket.
- If the bucket was just created, wait 60-120s for global consistency and re-run `tofu init`.
Example fix
# before
terraform {
backend "s3" {
bucket = "my-state-bukcet" # typo
}
}
# after
terraform {
backend "s3" {
bucket = "my-state-bucket"
}
} Defensive patterns
Strategy: validation
Validate before calling
// preflight: head the bucket with the exact credentials tofu will use
ctx := context.Background()
_, err := s3Client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucketName)})
if err != nil { return fmt.Errorf("bucket %s not visible: %w", bucketName, err) } Type guard
func isNoSuchBucketErr(err error) bool {
var nsb *s3types.NoSuchBucket
return errors.As(err, &nsb) || strings.Contains(err.Error(), "NoSuchBucket")
} Prevention
- Pre-create the state bucket before `tofu init`.
- Pin backend `bucket` and `region` via a config lint step.
- Use `aws s3api head-bucket` as a CI preflight with the same profile.
When it happens
Trigger: s3.NewListObjectsV2Paginator(...).NextPage(ctx) errors and the error type-asserts to *s3types.NoSuchBucket. The bucket b.bucketName does not exist in the configured account/region, or the credentials point at the wrong account.
Common situations: Typo in `bucket` in the S3 backend block; bucket in a different region than configured; bucket in a different AWS account and the principal has no cross-account access; bucket literally not yet created; wrong profile/role assumed so the caller sees a different account.
Related errors
- S3 bucket does not exist. The referenced S3 bucket must…
- can't delete default state
- Error unlocking S3 state. Lock ID
- failed to lock s3 state
- failed to upload state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/69e93064e83ad3f2.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/s3/backend_state.go:72
)
params := &s3.ListObjectsV2Input{
Bucket: aws.String(b.bucketName),
Prefix: aws.String(prefix),
MaxKeys: aws.Int32(maxKeys),
}
wss := []string{backend.DefaultStateName}
ctx, baselog := baselogging.NewHcLogger(ctx, log)
ctx = baselogging.RegisterLogger(ctx, baselog)
pages := s3.NewListObjectsV2Paginator(b.s3Client, params)
for pages.HasMorePages() {
page, err := pages.NextPage(ctx)
if err != nil {
if IsA[*s3types.NoSuchBucket](err) {
return nil, diags.Append(fmt.Errorf(errS3NoSuchBucket, b.bucketName, err))
}
if foo, ok := As[smithy.APIError](err); b.workspaceKeyPrefix == defaultWorkspaceKeyPrefix && ok && foo.ErrorCode() == "AccessDenied" {
log.Warn("Unable to list non-default workspaces", "err", err.Error())
return wss[:1], nil
}
return nil, diags.Append(fmt.Errorf("Unable to list objects in S3 bucket %q with prefix %q: %w", b.bucketName, prefix, err))
}
for _, obj := range page.Contents {
ws := b.keyEnv(aws.ToString(obj.Key))
if ws != "" {
wss = append(wss, ws)
}
}
}
sort.Strings(wss[1:])
return wss, diagsView on GitHub (pinned to d32a084675)