hashicorp/terraform · error

S3 bucket %q 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 in Backend.Workspaces (s3/backend_state.go:72) when the ListObjectsV2 paginator returns a *s3types.NoSuchBucket error. The configured bucket cannot be found by the caller's credentials in the resolved region. Terraform explicitly special-cases NoSuchBucket to give this actionable multi-line message.

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, diags

View on GitHub (pinned to c9def3e214)

Solutions

  1. Verify the bucket name and region in the backend config against `aws s3 ls`.
  2. Confirm the caller identity (`aws sts get-caller-identity`) is in the account that owns the bucket.
  3. Create the bucket if it is genuinely missing.
  4. If just created, wait one to two minutes for S3 consistency and retry.

Example fix

// before
// backend "s3" { bucket = "myco-tfstate" region = "us-east-1" }

// after (correct bucket/region)
// backend "s3" { bucket = "mycorp-terraform-state" region = "us-west-2" }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the bucket exists and is in the expected region before init
// out, err := s3Client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)})
// if err != nil { log.Fatalf("bucket missing/inaccessible: %v", err) }
// region := aws.ToString(out.BucketRegion)

Prevention

When it happens

Trigger: Typo in the bucket name; bucket lives in a different AWS account or region than the resolved credentials; AssumeRole resolved to the wrong account; bucket was deleted; bucket just created and not yet consistent.

Common situations: Wrong region in the backend block; AWS_PROFILE/AssumeRole pointing at the wrong account; bucket name with a stray suffix; Terraform run started immediately after bucket creation.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/d045e6d2f7c843b8. Report an issue: GitHub.