{"record":{"id":"ea82ec947c8a13fe","repo":"hashicorp/packer","slug":"must-contain-only-letters-digits-and-dashes-and","errorCode":null,"errorMessage":"must contain only letters, digits, and dashes, and may not use leading or trailing dashes: %w","messagePattern":"must contain only letters, digits, and dashes, and may not use leading or trailing dashes: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hcl2template/addrs/plugin.go","lineNumber":89,"sourceCode":"\t// The idna library doesn't expose individual label parsing directly, but\n\t// once we've verified it doesn't contain any dots we can just treat it\n\t// like a top-level domain for this library's purposes.\n\tif strings.ContainsRune(given, '.') {\n\t\treturn \"\", fmt.Errorf(\"dots are not allowed\")\n\t}\n\n\t// We don't allow names containing multiple consecutive dashes, just as\n\t// a matter of preference: they look confusing, or incorrect.\n\t// This also, as a side-effect, prevents the use of the \"punycode\"\n\t// indicator prefix \"xn--\" that would cause the IDNA library to interpret\n\t// the given name as punycode, because that would be weird and unexpected.\n\tif strings.Contains(given, \"--\") {\n\t\treturn \"\", fmt.Errorf(\"cannot use multiple consecutive dashes\")\n\t}\n\n\tresult, err := idna.Lookup.ToUnicode(given)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"must contain only letters, digits, and dashes, and may not use leading or trailing dashes: %w\", err)\n\t}\n\n\treturn result, nil\n}\n\n// IsPluginPartNormalized compares a given string to the result of ParsePluginPart(string)\nfunc IsPluginPartNormalized(str string) (bool, error) {\n\tnormalized, err := ParsePluginPart(str)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif str == normalized {\n\t\treturn true, nil\n\t}\n\treturn false, nil\n}\n\n// ParsePluginSourceString parses the source attribute and returns a plugin.","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/hcl2template/addrs/plugin.go#L71-L107","documentation":"ParsePluginPart runs idna.Lookup.ToUnicode on the plugin source component. If that fails, the component is not a valid IDNA label: it must contain only letters, digits, and dashes, without leading or trailing dashes. The IDNA library error is wrapped with %w for inspection.","triggerScenarios":"ParsePluginPart (or ParsePluginSourceString / checkPluginNameNormalized) given a component with characters outside [a-zA-Z0-9-], or one starting/ending with '-', e.g. 'github.com/hashicorp/packer_plugin', '-amazon-', or 'amazon!'.","commonSituations":"Underscores in plugin names (common mistake, since repos often use them); special characters from copy-paste; trailing dash left from editing; uppercase is fine but symbols are not.","solutions":["Replace invalid characters (underscores, dots, symbols) with dashes or remove them","Remove any leading or trailing dashes from the component","Verify the source address against the documented format 'github.com/org/name'"],"exampleFix":"// before\nsource \"github.com/hashicorp/packer_plugin_amazon\"\n// after\nsource \"github.com/hashicorp/packer-plugin-amazon\"","handlingStrategy":"validation","validationCode":"func validChars(s string) bool {\n  for _, r := range s {\n    if !(r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || r == '-') { return false }\n  }\n  return len(s) > 0 && s[0] != '-' && s[len(s)-1] != '-'\n}","typeGuard":"func isIDNASafe(s string) bool { _, err := idna.Lookup.ToUnicode(s); return err == nil }","tryCatchPattern":null,"preventionTips":["Replace underscores with dashes in plugin identifiers","Reject or sanitize non-ASCII/symbol characters before building source strings","Trim leading/trailing dashes from user-supplied names"],"tags":["validation","plugin-source","idna","hcl2"],"backgroundTag":"invalid-plugin-source-address","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"}