juanfont/headscale · error

%s confirm form: unterminated input tag

Error message

%s confirm form: unterminated input tag

What it means

After locating the `<input` tag for the CSRF field, the parser could not find a closing `>` in the remainder of the document (`strings.Index(htmlBody[tagStart:], ">")` returned -1). The tag is never terminated, so its attributes cannot be sliced out safely.

Source

Thrown at integration/scenario.go:1282

	}

	formAction := htmlBody[actionStart : actionStart+actionEnd]

	// Extract hidden CSRF input value. The rendered <input> has
	// attributes in name-type-value order so we grab the whole tag.
	before, _, ok := strings.Cut(htmlBody, `name="headscale_register_confirm"`)
	if !ok {
		return "", nil, fmt.Errorf("%s confirm form: no CSRF input", hostname) //nolint:err113
	}

	tagStart := strings.LastIndex(before, "<input")
	if tagStart == -1 {
		return "", nil, fmt.Errorf("%s confirm form: no input tag for CSRF", hostname) //nolint:err113
	}

	tagEnd := strings.Index(htmlBody[tagStart:], ">")
	if tagEnd == -1 {
		return "", nil, fmt.Errorf("%s confirm form: unterminated input tag", hostname) //nolint:err113
	}

	inputTag := htmlBody[tagStart : tagStart+tagEnd+1]

	valIdx := strings.Index(inputTag, `value="`)
	if valIdx == -1 {
		return "", nil, fmt.Errorf("%s confirm form: no value in CSRF input", hostname) //nolint:err113
	}

	valStart := valIdx + len(`value="`)
	valEnd := strings.Index(inputTag[valStart:], `"`)
	csrfToken := inputTag[valStart : valStart+valEnd]

	// Build the absolute POST URL from the response's request URL.
	base := prevResp.Request.URL
	confirmURL := &url.URL{
		Scheme: base.Scheme,
		Host:   base.Host,

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Dump `htmlBody` length and tail when the error fires to confirm truncation.
  2. Retry the GET of the confirm page; transient truncation in containerized tests is usually network flake.
  3. If reproducible, fix the template that renders the unterminated input tag.
Defensive patterns

Strategy: retry

Prevention

When it happens

Trigger: The document ends (or is truncated) between `<input` and its closing angle bracket — truncated response body, connection cut mid-body, or a template that emits a malformed input tag.

Common situations: Proxy or test harness truncates the HTML body; template file corrupted or partially written; the page is streamed and read before completion.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/f8dcef6afc26d10c. Report an issue: GitHub.