nats-io/nats-server · error

expected 1 byte when un-escaping, got %d

Error message

expected 1 byte when un-escaping, got %d

What it means

ParseDN decodes hex escapes into a single-byte buffer. If encoding/hex.Decode reports it consumed/produced a count other than 1 byte, the escape was not a valid single-byte pair, and this error is returned.

Source

Thrown at internal/ldap/dn.go:165

		case escaping:
			unescapedTrailingSpaces = 0
			escaping = false
			switch char {
			case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
				buffer.WriteByte(char)
				continue
			}
			// Not a special character, assume hex encoded octet
			if len(str) == i+1 {
				return nil, errors.New("got corrupted escaped character")
			}

			dst := []byte{0}
			n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
			if err != nil {
				return nil, fmt.Errorf("failed to decode escaped character: %s", err)
			} else if n != 1 {
				return nil, fmt.Errorf("expected 1 byte when un-escaping, got %d", n)
			}
			buffer.WriteByte(dst[0])
			i++
		case char == '\\':
			unescapedTrailingSpaces = 0
			escaping = true
		case char == '=':
			attribute.Type = stringFromBuffer()
			// Special case: If the first character in the value is # the following data
			// is BER encoded. Throw an error since not supported right now.
			if len(str) > i+1 && str[i+1] == '#' {
				return nil, errors.New("unsupported BER encoding")
			}
		case char == ',' || char == '+':
			// We're done with this RDN or value, push it
			if len(attribute.Type) == 0 {
				return nil, errors.New("incomplete type, value pair")
			}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Ensure each backslash escape is followed by exactly two hex characters and the DN is not truncated
  2. Trim/repair the DN source (file, env var, config) of stray whitespace or truncation
  3. Pre-validate DN length/escaping before calling ParseDN

Example fix

// before
dn, err := ParseDN("CN=Server\4")
// after
dn, err := ParseDN("CN=Server\40")
Defensive patterns

Strategy: validation

Validate before calling

if len(dn) >= 1 && strings.HasSuffix(dn, "\\") {
    return fmt.Errorf("DN %q ends with dangling escape", dn)
}
if !dnEscapeSequenceRegex.MatchString(dn) {
    return fmt.Errorf("DN %q has invalid escape sequence", dn)
}

Try / catch

dn, err := ParseDN(input)
if err != nil {
    if strings.Contains(err.Error(), "expected 1 byte when un-escaping") {
        return fmt.Errorf("truncated escape in DN %q: %w", input, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ParseDN with a DN whose escape sequence decodes to something other than one byte — practically triggered by malformed input that slips past basic validation, or by a sliced escape substring shorter than 2 bytes at the end of the string.

Common situations: Truncated escape at end of DN string ("CN=A\4"), corrupted DN data read from files or network, off-by-one in DN-manipulation code that slices the string before parsing.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/4b5dc47c266f8259. Report an issue: GitHub.