{"record":{"id":"d0d59b2d9238796c","repo":"slimtoolkit/slim","slug":"malformed-healthcheck-instruction-q","errorCode":null,"errorMessage":"malformed HEALTHCHECK instruction: %q","messagePattern":"malformed HEALTHCHECK instruction: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/docker/dockerfile/reverse/reverse.go","lineNumber":785,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\tlog.Errorf(\"[%s] config.Retries err = %v\", vparts[0], err)\n\t\t\t} else {\n\t\t\t\tconfig.Retries = int(retries)\n\t\t\t}\n\t\t}\n\n\t\tif strings.Contains(cleanInst, \" CMD \") {\n\t\t\tparts := strings.SplitN(cleanInst, \" CMD \", 2)\n\t\t\tstrTest = fmt.Sprintf(\"CMD %s\", parts[1])\n\t\t\tconfig.Test = []string{\"CMD\", parts[1]}\n\t\t}\n\t} else {\n\t\tcleanInst = strings.Replace(cleanInst, \"&{[\", \"\", -1)\n\n\t\t//Splits the string into two parts - first part pointer to array of string and rest of the string with } in end.\n\t\tinstParts := strings.SplitN(cleanInst, \"]\", 2)\n\t\tif len(instParts) < 2 {\n\t\t\treturn strTest, &config, fmt.Errorf(\"malformed HEALTHCHECK instruction: %q\", data)\n\t\t}\n\t\t// Cleans HEALTHCHECK part and splits the first part further\n\t\tparts := strings.SplitN(instParts[0], \" \", 2)\n\t\t// joins the first part of the string\n\t\tinstPart1 := strings.Join(parts[1:], \" \")\n\t\t// removes quotes from the first part of the string\n\t\tinstPart1 = strings.ReplaceAll(instPart1, \"\\\"\", \"\")\n\n\t\t// cleans it to assign it to the pointer config.Test\n\t\tconfig.Test = strings.Split(instPart1, \" \")\n\n\t\t// removes the } from the second part of the string\n\t\tinstPart2 := strings.Replace(instParts[1], \"}\", \"\", -1)\n\t\t// removes extra spaces from string\n\t\tinstPart2 = strings.TrimSpace(instPart2)\n\n\t\tparamParts := strings.SplitN(instPart2, \" \", 4)\n\t\tif len(paramParts) < 4 {","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/docker/dockerfile/reverse/reverse.go#L767-L803","documentation":"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.","triggerScenarios":"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 \"]\").","commonSituations":"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.","solutions":["Inspect the image's healthcheck config (docker inspect --format '{{json .Config.Healthcheck}}' <image>) and verify the Test array.","Handle/normalize the NONE case (Test == [\"NONE\"]) before reverse conversion if your source config lacks it.","Fix the tooling that produced the malformed config so Test is a proper JSON array like [\"CMD-SHELL\", \"curl -f http://localhost/ || exit 1\"].","If the image itself is broken, rebuild it with a valid HEALTHCHECK instruction in the Dockerfile."],"exampleFix":"// before (config with empty healthcheck)\n\"Healthcheck\": {\"Test\": null}\n// after\n\"Healthcheck\": {\"Test\": [\"CMD-SHELL\", \"curl -f http://localhost/ || exit 1\"], \"Interval\": 30000000000}","handlingStrategy":"type-guard","validationCode":"hc := imgCfg.Config.Healthcheck\nif hc == nil || len(hc.Test) == 0 || (len(hc.Test) == 1 && hc.Test[0] == \"NONE\") {\n    // skip reverse-HEALTHCHECK or emit 'HEALTHCHECK NONE' instead\n}","typeGuard":"func hasReconstructibleHealthcheck(hc *container.HealthConfig) bool {\n    return hc != nil && len(hc.Test) >= 2 && hc.Test[0] != \"NONE\"\n}","tryCatchPattern":"inst, cfg, err := reverse.Healthcheck(imgCfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"malformed HEALTHCHECK instruction\") {\n        log.Warnf(\"skipping HEALTHCHECK reversal: %v\", err)\n        return \"HEALTHCHECK NONE\", nil, nil\n    }\n    return err\n}","preventionTips":["Verify image configs with docker inspect before reverse conversion.","Treat Test=[\"NONE\"] (or empty) as HEALTHCHECK NONE and short-circuit.","Avoid hand-editing image configs; rebuild images with valid HEALTHCHECK instructions.","Write a round-trip test (Dockerfile -> config -> Dockerfile) to catch format drift."],"tags":["go","dockerfile","healthcheck","reverse-conversion"],"backgroundTag":"malformed-healthcheck-config","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}