hashicorp/terraform · error
Invalid URL: %v must be: %v
Error message
Invalid URL: %v must be: %v
What it means
Raised in Backend.configure() (cos/backend.go:309) when the `endpoint` attribute is set but does not match the strict regex ^(http(s)?)://cos-internal\.([^.]+)\.tencentcos\.cn$. The endpoint option only accepts the COS internal-access form; any other URL shape is rejected.
Source
Thrown at internal/backend/remote-state/cos/backend.go:309
u, err = url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", b.bucket, b.region))
}
if err != nil {
return err
}
if v, ok := data.GetOk("domain"); ok {
b.domain = v.(string)
log.Printf("[DEBUG] Backend: set domain for TencentCloud API client. Domain: [%s]", b.domain)
}
// set url as endpoint when provided
// "http://{Bucket}.cos-internal.{Region}.tencentcos.cn"
if v, ok := data.GetOk("endpoint"); ok {
endpoint := v.(string)
re := regexp.MustCompile(`^(http(s)?)://cos-internal\.([^.]+)\.tencentcos\.cn$`)
matches := re.FindStringSubmatch(endpoint)
if len(matches) != 4 {
return fmt.Errorf("Invalid URL: %v must be: %v", endpoint, "http(s)://cos-internal.{Region}.tencentcos.cn")
}
protocol := matches[1]
region := matches[3]
// URL after converting
newUrl := fmt.Sprintf("%s://%s.cos-internal.%s.tencentcos.cn", protocol, b.bucket, region)
u, err = url.Parse(newUrl)
log.Printf("[DEBUG] Backend: set COS URL as: [%s]", newUrl)
}
if err != nil {
return err
}
var getProviderConfig = func(key string) string {
var str string
value, err := getConfigFromProfile(data, key)
if err == nil && value != nil {View on GitHub (pinned to c9def3e214)
Solutions
- Use the exact form endpoint = "https://cos-internal.ap-guangzhou.tencentcos.cn" with a real region.
- If you want the public endpoint, omit the endpoint attribute entirely; the backend builds the public URL from region/bucket.
- Verify the region segment matches a valid TencentCloud region.
Example fix
// before
terraform {
backend "cos" {
region = "ap-guangzhou"
bucket = "my-bucket"
endpoint = "https://cos.ap-guangzhou.myqcloud.com"
}
}
// after
terraform {
backend "cos" {
region = "ap-guangzhou"
bucket = "my-bucket"
endpoint = "https://cos-internal.ap-guangzhou.tencentcos.cn"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the cos endpoint matches the internal-access form
var endpointRe = regexp.MustCompile(`^(http(s)?)://cos-internal\.([^.]+)\.tencentcos\.cn$`)
func validEndpoint(ep string) error {
if len(endpointRe.FindStringSubmatch(ep)) != 4 {
return fmt.Errorf("Invalid URL: %v must be: %v", ep, "http(s)://cos-internal.{Region}.tencentcos.cn")
}
return nil
} Prevention
- Only set endpoint for COS internal access, in the exact required form.
- Omit endpoint to use the default public COS URL built from region/bucket.
- Keep the region segment in the endpoint consistent with the configured region.
When it happens
Trigger: Configuring endpoint = "https://cos.ap-guangzhou.myqcloud.com" or any string that does not exactly match http(s)://cos-internal.<region>.tencentcos.cn; the regex match returns fewer than 4 groups.
Common situations: Trying to use the public COS endpoint via the endpoint option (not supported - endpoint is internal-only); typos in the domain; wrong region segment; missing protocol.
Related errors
- prefix must not start with '/' or './'
- key can not start and end with '/'
- acl value invalid, expected %s or %s, got %s
- %q cannot be lower than %d: %d
- %q cannot be higher than %d: %d
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/0919cc1972392b7a.
Report an issue: GitHub.