{"record":{"id":"2ef720c1b5b50b0f","repo":"hashicorp/packer","slug":"ssh-private-ip-is-not-a-boolean-s","errorCode":null,"errorMessage":"ssh_private_ip is not a boolean, %s","messagePattern":"ssh_private_ip is not a boolean, (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fix/fixer_amazon_private_ip.go","lineNumber":65,"sourceCode":"\t\tif !strings.HasPrefix(builderType, \"amazon-\") {\n\t\t\tcontinue\n\t\t}\n\n\t\t// if ssh_interface already set, do nothing\n\t\tif _, ok := builder[\"ssh_interface\"]; ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tprivateIPi, ok := builder[\"ssh_private_ip\"]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tprivateIP, ok := privateIPi.(bool)\n\t\tif !ok {\n\t\t\tvar err error\n\t\t\tprivateIP, err = strconv.ParseBool(privateIPi.(string))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"ssh_private_ip is not a boolean, %s\", err)\n\t\t\t}\n\t\t}\n\n\t\tdelete(builder, \"ssh_private_ip\")\n\t\tif privateIP {\n\t\t\tbuilder[\"ssh_interface\"] = \"private_ip\"\n\t\t} else {\n\t\t\tbuilder[\"ssh_interface\"] = \"public_ip\"\n\t\t}\n\t}\n\n\tinput[\"builders\"] = tpl.Builders\n\treturn input, nil\n}\n\nfunc (FixerAmazonPrivateIP) Synopsis() string {\n\treturn \"Replaces `\\\"ssh_private_ip\\\": true` in amazon builders with `\\\"ssh_interface\\\": \\\"private_ip\\\"`\"\n}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/fix/fixer_amazon_private_ip.go#L47-L83","documentation":"The amazon-private_ip fixer migrates the deprecated builder-level `ssh_private_ip` key to `ssh_interface`. If the value is neither a bool nor a string parseable by strconv.ParseBool (\"true\",\"false\",\"1\",\"0\", etc.), the fixer aborts with this error wrapping the parse error.","triggerScenarios":"Running `packer fix` on a JSON template where amazon builders contain `ssh_private_ip` set to a non-boolean, unparseable value like \"yes\", \"on\", or a number.","commonSituations":"Hand-edited legacy templates, templates generated by other tooling using YAML-ish truthy strings, or values produced by template engines that stringified booleans.","solutions":["Edit the template so ssh_private_ip is a JSON boolean true/false (or string \"true\"/\"false\")","Let the fixer complete, then remove ssh_private_ip in favor of the generated ssh_interface key","If you want 'private_ip' semantics, after fixing use ssh_interface = \"private_ip\""],"exampleFix":"// before\n\"ssh_private_ip\": \"yes\"\n// after\n\"ssh_private_ip\": true","handlingStrategy":"validation","validationCode":"// pre-check fixer input in CI\nif v, ok := tpl[\"ssh_private_ip\"]; ok {\n  switch v.(type) { case bool, string: if _, err := strconv.ParseBool(fmt.Sprint(v)); err != nil && !ok2(v) { /* reject */ } }\n}","typeGuard":"func isBoolLike(v interface{}) bool {\n  if _, ok := v.(bool); ok { return true }\n  s, ok := v.(string); if !ok { return false }\n  _, err := strconv.ParseBool(s); return err == nil\n}","tryCatchPattern":null,"preventionTips":["Keep booleans as JSON booleans in templates","Audit legacy templates with `packer fix` in a dry CI step before migration","Avoid template engines that stringify booleans ('yes'/'on')"],"tags":["fixer","amazon","migration","parsing"],"backgroundTag":"invalid-boolean-value","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}