opentofu/opentofu · error

failed to parse address URL: %w

Error message

failed to parse address URL: %w

What it means

During configure(), the 'address' attribute is parsed with url.Parse and any error is wrapped as 'failed to parse address URL'. url.Parse rarely fails, but it does for structurally malformed URLs such as an unclosed IPv6 bracket or embedded control characters, so this fires before the http/https scheme check.

Source

Thrown at internal/backend/remote-state/http/backend.go:215

	if clientCertificatePem != "" && clientPrivateKeyPem != "" {
		// attach a client certificate to the TLS handshake (aka mTLS)
		certificate, err := tls.X509KeyPair([]byte(clientCertificatePem), []byte(clientPrivateKeyPem))
		if err != nil {
			return fmt.Errorf("cannot load client certificate: %w", err)
		}
		tlsConfig.Certificates = []tls.Certificate{certificate}
	}

	return nil
}

func (b *Backend) configure(ctx context.Context) error {
	data := schema.FromContextBackendConfig(ctx)

	address := data.Get("address").(string)
	updateURL, err := url.Parse(address)
	if err != nil {
		return fmt.Errorf("failed to parse address URL: %w", err)
	}
	if updateURL.Scheme != "http" && updateURL.Scheme != "https" {
		return fmt.Errorf("address must be HTTP or HTTPS")
	}

	updateMethod := data.Get("update_method").(string)

	var lockURL *url.URL
	if v, ok := data.GetOk("lock_address"); ok && v.(string) != "" {
		var err error
		lockURL, err = url.Parse(v.(string))
		if err != nil {
			return fmt.Errorf("failed to parse lockAddress URL: %w", err)
		}
		if lockURL.Scheme != "http" && lockURL.Scheme != "https" {
			return fmt.Errorf("lockAddress must be HTTP or HTTPS")
		}
	}

View on GitHub (pinned to 3561785c48)

Solutions

  1. Print the fully rendered address and test it with curl to confirm it parses
  2. Fix the malformed component (close brackets, remove spaces, control characters, newlines)
  3. Set the complete URL as a single literal in the backend block instead of concatenating variables

Example fix

# before
address = "https://[::1"
# after
address = "https://[::1]/state"
Defensive patterns

Strategy: validation

Validate before calling

// Validate the rendered address before tofu init
u, err := url.Parse(rawAddress)
if err != nil {
    log.Fatalf("address does not parse: %v", err)
}

Prevention

When it happens

Trigger: address = "https://[::1" (missing ']'), an address containing a control character or newline (often from a templated variable), or garbage produced by concatenating empty config pieces.

Common situations: Assembling the URL from multiple -backend-config flags or CI variables where one piece is empty or mangled; IPv6 literals typed by hand; secrets managers or env files returning values with trailing newlines.

Understand the failure class

Related errors


AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15). Data as JSON: /api/errors/e7affb113dc21c77. Report an issue: GitHub.