hashicorp/terraform · error

failed to delete file

Error message

failed to delete file %v: %v

What it means

Returned by deleteObject() when the COS SDK returns a nil response pointer from Object.Delete. Same transport-failure shape as 201/206 but on the DELETE path: no HTTP response was received at all.

Solutions

  1. Inspect the wrapped error and DEBUG line `deleteObject <file>: error:`.
  2. Verify credentials and region/endpoint configuration.
  3. Confirm outbound connectivity to `cos.<region>.myqcloud.com`.
  4. Retry after resolving the transport cause.

Example fix

// before: stale credentials cause DELETE to fail with nil response
export TENCENTCLOUD_SECRETID=old_id
// after: refresh credentials
export TENCENTCLOUD_SECRETID=new_id
export TENCENTCLOUD_SECRETKEY=new_key
Defensive patterns

Strategy: retry

Validate before calling

// Validate delete-path connectivity before relying on it (e.g. force-unlock)
func canDeleteObject(ctx context.Context, client *cos.Client, key string) error {
    rsp, err := client.Object.Delete(ctx, key+".probe")
    if rsp == nil { return fmt.Errorf("transport failure deleting from COS: %w", err) }
    rsp.Body.Close()
    return nil // 404 is fine here
}

Type guard

func isNilDeleteResponse(rsp *cos.Response) bool { return rsp == nil }

Try / catch

// Retry nil-response deletes as transport errors:
backoff.Retry(func() error {
    rsp, err := client.Object.Delete(ctx, key)
    if rsp == nil { return err } // retryable
    defer rsp.Body.Close()
    if rsp.StatusCode == 404 { return nil }
    if err != nil { return backoff.Permanent(err) }
    return nil
}, backoff.NewExponentialBackOff())

Prevention

When it happens

Trigger: c.cosClient.Object.Delete(...) returns (nil, err) due to network failure, bad endpoint, missing/invalid credentials, or context cancellation before any response.

Common situations: Same as 201/206: misconfigured region/endpoint, expired SecretId/SecretKey, no outbound connectivity to COS, or the parent operation was cancelled.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/6845f9d67714df63. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/remote-state/cos/client.go:264

		log.Printf("[DEBUG] putObject %s: error: %v", cosFile, err)
		return fmt.Errorf("failed to save file to %v: %v", cosFile, err)
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] putObject %s: code: %d, error: %v", cosFile, rsp.StatusCode, err)
	if err != nil {
		return fmt.Errorf("failed to save file to %v: %v", cosFile, err)
	}

	return nil
}

// deleteObject delete remote object
func (c *remoteClient) deleteObject(cosFile string) error {
	rsp, err := c.cosClient.Object.Delete(c.cosContext, cosFile)
	if rsp == nil {
		log.Printf("[DEBUG] deleteObject %s: error: %v", cosFile, err)
		return fmt.Errorf("failed to delete file %v: %v", cosFile, err)
	}
	defer rsp.Body.Close()

	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})

View on GitHub (pinned to d32a084675)