slimtoolkit/slim · error

malformed HEALTHCHECK instruction: %q

Error message

malformed HEALTHCHECK instruction: %q

What it means

The reverse (Dockerfile-from-image-config) converter reconstructs a HEALTHCHECK instruction from the image config's Healthcheck struct. The stringified test array is expected in a "&{[...] }" shape; after removing "&{[", it splits on "]" and requires at least two parts. If the structure doesn't match — missing the closing bracket — it cannot reconstruct the instruction and returns this error quoting the raw data.

Source

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

			if err != nil {
				log.Errorf("[%s] config.Retries err = %v", vparts[0], err)
			} else {
				config.Retries = int(retries)
			}
		}

		if strings.Contains(cleanInst, " CMD ") {
			parts := strings.SplitN(cleanInst, " CMD ", 2)
			strTest = fmt.Sprintf("CMD %s", parts[1])
			config.Test = []string{"CMD", parts[1]}
		}
	} else {
		cleanInst = strings.Replace(cleanInst, "&{[", "", -1)

		//Splits the string into two parts - first part pointer to array of string and rest of the string with } in end.
		instParts := strings.SplitN(cleanInst, "]", 2)
		if len(instParts) < 2 {
			return strTest, &config, fmt.Errorf("malformed HEALTHCHECK instruction: %q", data)
		}
		// Cleans HEALTHCHECK part and splits the first part further
		parts := strings.SplitN(instParts[0], " ", 2)
		// joins the first part of the string
		instPart1 := strings.Join(parts[1:], " ")
		// removes quotes from the first part of the string
		instPart1 = strings.ReplaceAll(instPart1, "\"", "")

		// cleans it to assign it to the pointer config.Test
		config.Test = strings.Split(instPart1, " ")

		// removes the } from the second part of the string
		instPart2 := strings.Replace(instParts[1], "}", "", -1)
		// removes extra spaces from string
		instPart2 = strings.TrimSpace(instPart2)

		paramParts := strings.SplitN(instPart2, " ", 4)
		if len(paramParts) < 4 {

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Inspect the image's healthcheck config (docker inspect --format '{{json .Config.Healthcheck}}' <image>) and verify the Test array.
  2. Handle/normalize the NONE case (Test == ["NONE"]) before reverse conversion if your source config lacks it.
  3. Fix the tooling that produced the malformed config so Test is a proper JSON array like ["CMD-SHELL", "curl -f http://localhost/ || exit 1"].
  4. If the image itself is broken, rebuild it with a valid HEALTHCHECK instruction in the Dockerfile.

Example fix

// before (config with empty healthcheck)
"Healthcheck": {"Test": null}
// after
"Healthcheck": {"Test": ["CMD-SHELL", "curl -f http://localhost/ || exit 1"], "Interval": 30000000000}
Defensive patterns

Strategy: type-guard

Validate before calling

hc := imgCfg.Config.Healthcheck
if hc == nil || len(hc.Test) == 0 || (len(hc.Test) == 1 && hc.Test[0] == "NONE") {
    // skip reverse-HEALTHCHECK or emit 'HEALTHCHECK NONE' instead
}

Type guard

func hasReconstructibleHealthcheck(hc *container.HealthConfig) bool {
    return hc != nil && len(hc.Test) >= 2 && hc.Test[0] != "NONE"
}

Try / catch

inst, cfg, err := reverse.Healthcheck(imgCfg)
if err != nil {
    if strings.Contains(err.Error(), "malformed HEALTHCHECK instruction") {
        log.Warnf("skipping HEALTHCHECK reversal: %v", err)
        return "HEALTHCHECK NONE", nil, nil
    }
    return err
}

Prevention

When it happens

Trigger: Converting an image config to Dockerfile when config.Healthcheck.Test is nil/empty or the marshaled test string lacks the expected "&{[cmd...] }" layout (len(instParts) < 2 after splitting on "]").

Common situations: Images built/modified by tools that store HEALTHCHECK in a non-standard format; images with an empty healthcheck test array (NONE variant mishandled); hand-edited image configs or OCI-converted metadata losing the expected shape.

Understand the failure class

Related errors


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