slimtoolkit/slim · error

expected retries (%s) to be an escape sequence

Error message

expected retries (%s) to be an escape sequence

What it means

During HEALTHCHECK reverse parsing, the retries value (paramParts[3]) starts with a backslash, so the parser assumes it is an escape sequence (C-escape or unicode \U form). An escape must be exactly 2 characters (e.g. \n); a longer or shorter backslash-prefixed token cannot be decoded into the numeric retries value, so the builder records this error on the returned err.

Source

Thrown at pkg/docker/dockerfile/reverse/reverse.go:836

			log.Errorf("[%s] config.Timeout err = %v", paramParts[1], err)
		}

		config.StartPeriod, err = time.ParseDuration(paramParts[2])
		if err != nil {
			log.Errorf("[%s] config.StartPeriod err = %v", paramParts[2], err)
		}

		var retries int64
		if strings.Index(paramParts[3], `\x`) != -1 {
			// retries are hex encoded
			retries, err = strconv.ParseInt(strings.TrimPrefix(paramParts[3], `\x`), 16, 64)
		} else if strings.Index(paramParts[3], `\U`) != -1 {
			// retries are a unicode string
			retries, err = strconv.ParseInt(strings.TrimPrefix(paramParts[3], `\U`), 16, 64)
		} else if strings.Index(paramParts[3], `\`) == 0 {
			// retries is printed as a C-escape
			if len(paramParts[3]) != 2 {
				err = fmt.Errorf("expected retries (%s) to be an escape sequence", paramParts[3])
			} else {
				escapeCodes := map[byte]int64{
					byte('a'): 7,
					byte('b'): 8,
					byte('t'): 9,
					byte('n'): 10,
					byte('v'): 11,
					byte('f'): 12,
					byte('r'): 13,
				}
				var ok bool
				if retries, ok = escapeCodes[(paramParts[3])[1]]; !ok {
					err = fmt.Errorf("got an invalid escape sequence: %s", paramParts[3])
				}
			}
		} else if len(paramParts[3]) > 0 {
			retries = int64((paramParts[3])[0])
		}

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Fix the retries parameter in the image history/config so it is a single escape sequence like \n, \t, a \Uxxxx unicode escape, or a plain numeric value.
  2. Remove the HEALTHCHECK metadata from the image config if the retries value cannot be corrected.
  3. Verify the history string was not backslash-escaped twice by the build tooling and re-ingest the image.

Example fix

// before (malformed multi-char escape)
HEALTHCHECK --retries=\\n\\ ["CMD", "curl", "-f", "http://localhost/"]
// after (valid escape)
HEALTHCHECK --retries=3 ["CMD", "curl", "-f", "http://localhost/"]
Defensive patterns

Strategy: validation

Validate before calling

// retries must be a 2-char escape, \Uxxxx, or plain value
func validRetries(p string) bool {
	if !strings.HasPrefix(p, "\\") { return true }
	if strings.HasPrefix(p, "\\U") { return len(p) == 6 }
	return len(p) == 2
}

Try / catch

if err := buildErr; err != nil && strings.Contains(err.Error(), "expected retries") {
	// sanitize or drop the HEALTHCHECK metadata, then rebuild
}

Prevention

When it happens

Trigger: A HEALTHCHECK entry whose 4th parameter begins with a single backslash but is not exactly 2 characters long (e.g. \\n\\, or \\x1B, or a Windows-style path fragment) when running the reverse Dockerfile builder (FailOn/Error/Run/NewBasicImageBuilder).

Common situations: Images built on Windows or with shell-escaped retries values in history; history strings where backslashes were doubled or mangled by shell quoting; copy-pasted HEALTHCHECK metadata from docs.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/c0bfe41846fc438e. Report an issue: GitHub.