rancher/rancher · warning

cannot decode uuid string '%s' to hex: %w

Error message

cannot decode uuid string '%s' to hex: %w

What it means

Defensive branch in guid.Parse (pkg/auth/providers/activedirectory/guid/guid.go:85): after uuidRegex already validated the 8-4-4-4-12 hex-and-dash shape, hex.DecodeString on the dash-stripped string still failed. Because the regex admits only ASCII hex digits, decode cannot realistically fail on regex-passing input; malformed input instead fails earlier with 'cannot parse UUID to objectGUID: invalid format'.

Source

Thrown at pkg/auth/providers/activedirectory/guid/guid.go:85

// New returns a GUID object
func New(encoded []byte) (GUID, error) {
	if len(encoded) != 16 {
		return nil, errors.New("cannot create GUID from encoded bytes: invalid length")
	}

	return GUID(encoded), nil
}

// Parse returns a GUID object from a RFC4122 UUID string
func Parse(uuid string) (GUID, error) {
	if !uuidRegex.MatchString(uuid) {
		return nil, errors.New("cannot parse UUID to objectGUID: invalid format")
	}

	uuid = strings.ReplaceAll(uuid, "-", "")
	uuidBytes, err := hex.DecodeString(uuid)
	if err != nil {
		return nil, fmt.Errorf("cannot decode uuid string '%s' to hex: %w", uuid, err)
	}

	return GUID(swap(uuidBytes)), nil
}

// Escape returns an escaped string format of the objectGUID that can be safely used
// through the LDAP search. Every byte has to be encoded in an hex string,
// and prefixed with the '\' character. If a byte has a hex encoded string of
// length 1 then it will be prefixed with a '0'.
func Escape(guid GUID) string {
	builder := strings.Builder{}

	hexArray := hexes(guid.Bytes())
	for _, hex := range hexArray {
		builder.WriteString(`\`)
		builder.WriteString(hex)
	}

View on GitHub (pinned to 932558d4e6)

Solutions

  1. Validate and normalize the UUID string before calling guid.Parse
  2. If it ever fires, log the exact string: it indicates concurrent mutation or a modified regex
  3. Handle the invalid-format error for user-input validation; treat this one as an internal invariant violation
Defensive patterns

Strategy: type-guard

Type guard

var uuidRe = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)

func isRFC4122UUID(s string) bool { return uuidRe.MatchString(s) }

Try / catch

g, err := guid.Parse(uuidStr)
if err != nil {
	if strings.Contains(err.Error(), "invalid format") || strings.Contains(err.Error(), "cannot decode uuid string") {
		return fmt.Errorf("%q is not a valid objectGUID UUID", uuidStr)
	}
	return err
}

Prevention

When it happens

Trigger: The input string is mutated between the regex check and the decode (shared buffer across goroutines); a fork widened the regex to admit non-hex characters. In the shipped code the branch is effectively unreachable.

Common situations: Essentially never seen in production; the sibling invalid-format error is the one callers actually hit for malformed UUIDs.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/b4fef208d43fe82b. Report an issue: GitHub.