kubernetes/kops · error

unexpected line %q (expected 2 tokens)

Error message

unexpected line %q (expected 2 tokens)

What it means

run() parses the SHA256SUMS response line by line, skipping blank lines and known PGP boilerplate. Any non-empty line that does not split into exactly 2 whitespace-separated tokens (hash, filename) is rejected with this error. It guards against HTML error pages, comments, or unexpected formats corrupting the generated manifest.

Source

Thrown at pkg/assets/assetdata/tools/cmd/generatefileassets/main.go:90

		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		if line == "-----BEGIN PGP SIGNED MESSAGE-----" {
			// Start of the PGP boilerplate
			continue
		}
		if line == "-----BEGIN PGP SIGNATURE-----" {
			// Part of the PGP signature; end of signed content
			break
		}
		if line == "Hash: SHA256" {
			// Part of the PGP boilerplate
			continue
		}
		tokens := strings.Fields(line)
		if len(tokens) != 2 {
			return fmt.Errorf("unexpected line %q (expected 2 tokens)", line)
		}
		hash := tokens[0]
		name := tokens[1]
		name = removeBadPrefix(name)

		if exclude.Matches(prefix + name) {
			continue
		}
		m.Files = append(m.Files, file{
			Name:   prefix + name,
			SHA256: hash,
		})
	}

	out, err := yaml.Marshal(&m)
	if err != nil {
		return fmt.Errorf("building yaml: %w", err)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the URL content with curl; point -sums at the real plain-text SHA256SUMS file
  2. Preprocess/handle unusual lines: strip comments or extra columns, or extend the parser to skip them
  3. If PGP boilerplate differs, add the marker line to the skip list alongside 'Hash: SHA256'
  4. Verify you downloaded the sha256 (not sha512/md5) sums matching the expected 2-column format

Example fix

// before: HTML error page fed to parser
unexpected line "<html>..." (expected 2 tokens)
// after: correct sums URL
main -sums https://dl.k8s.io/.../SHA256SUMS ...
Defensive patterns

Strategy: validation

Validate before calling

func looksLikeSums(b []byte) bool {
	for _, line := range strings.Split(string(b), "\n") {
		line = strings.TrimSpace(line)
		if line == "" || strings.HasPrefix(line, "-----") || strings.HasPrefix(line, "Hash:") || strings.HasPrefix(line, "<") {
			continue
		}
		if len(strings.Fields(line)) != 2 {
			return false
		}
	}
	return true
}

Type guard

func isUnexpectedLineErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "unexpected line")
}

Try / catch

if err := run(ctx); err != nil {
	if isUnexpectedLineErr(err) {
		// dump the raw response to inspect what was actually fetched
	}
	return err
}

Prevention

When it happens

Trigger: The URL returned content that isn't a standard SHA256SUMS file: an HTML error/consent page, a GPG file with unhandled boilerplate lines, lines with extra tokens (checksum files with size columns), or wrapped/continuation lines.

Common situations: Pointing -sums at a login page or a directory listing; using a BSD-style checksum file or one with additional metadata columns; PGP headers differing from the three handled cases.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/d7daa6afab05360e. Report an issue: GitHub.