{"record":{"id":"aa4cfa6011827535","repo":"hashicorp/terraform","slug":"must-use-lowercase-hex-digits","errorCode":null,"errorMessage":"must use lowercase hex digits","messagePattern":"must use lowercase hex digits","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/addrs/resource.go","lineNumber":623,"sourceCode":"var deposedKeyRand = rand.New(rand.NewSource(time.Now().UnixNano()))\n\n// NewDeposedKey generates a pseudo-random deposed key. Because of the short\n// length of these keys, uniqueness is not a natural consequence and so the\n// caller should test to see if the generated key is already in use and generate\n// another if so, until a unique key is found.\nfunc NewDeposedKey() DeposedKey {\n\tv := deposedKeyRand.Uint32()\n\treturn DeposedKey(fmt.Sprintf(\"%08x\", v))\n}\n\n// ParseDeposedKey parses a string that is expected to be a deposed key,\n// returning an error if it doesn't conform to the expected syntax.\nfunc ParseDeposedKey(raw string) (DeposedKey, error) {\n\tif len(raw) != 8 {\n\t\treturn \"00000000\", fmt.Errorf(\"must be eight hexadecimal digits\")\n\t}\n\tif raw != strings.ToLower(raw) {\n\t\treturn \"00000000\", fmt.Errorf(\"must use lowercase hex digits\")\n\t}\n\t_, err := hex.DecodeString(raw)\n\tif err != nil {\n\t\treturn \"00000000\", fmt.Errorf(\"must be eight hexadecimal digits\")\n\t}\n\treturn DeposedKey(raw), nil\n}\n\nfunc (k DeposedKey) String() string {\n\treturn string(k)\n}\n\nfunc (k DeposedKey) GoString() string {\n\tks := string(k)\n\tswitch {\n\tcase ks == \"\":\n\t\treturn \"states.NotDeposed\"\n\tdefault:","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/addrs/resource.go#L605-L641","documentation":"Returned by addrs.ParseDeposedKey when the raw string is exactly 8 characters and decodes as hex, but contains uppercase letters (raw != strings.ToLower(raw)). DeposedKey is canonicalised to lowercase, so any uppercase input is rejected. Returns the zero key \"00000000\" on failure.","triggerScenarios":"ParseDeposedKey at resource.go:622-624 fires when len==8 and hex.DecodeString would succeed but the string is not all-lowercase. Reached from parsing deposed keys in CLI/state/addresses.","commonSituations":"User typed a deposed key in uppercase (e.g. 'A1B2C3D4'); tooling uppercased the key for display and it was round-tripped back; copy-paste from a formatter that capitalised hex.","solutions":["Lowercase the input before calling ParseDeposedKey (strings.ToLower), or supply lowercase to begin with.","Display deposed keys in lowercase in your UI to prevent round-trip breakage.","Validate with ^[0-9a-f]{8}$ (lowercase only) to surface a clear error early."],"exampleFix":"// before\nk, err := addrs.ParseDeposedKey(input) // input = \"A1B2C3D4\"\n\n// after\nk, err := addrs.ParseDeposedKey(strings.ToLower(input))","handlingStrategy":"validation","validationCode":"raw := strings.ToLower(strings.TrimSpace(input))\nif !regexp.MustCompile(`^[0-9a-f]{8}$`).MatchString(raw) {\n    return fmt.Errorf(\"deposed key must be 8 lowercase hex digits\")\n}","typeGuard":"func isLowercaseHexDeposedKey(s string) bool {\n    s = strings.TrimSpace(s)\n    return s == strings.ToLower(s) && regexp.MustCompile(`^[0-9a-f]{8}$`).MatchString(s)\n}","tryCatchPattern":"input = strings.ToLower(strings.TrimSpace(input))\nk, err := addrs.ParseDeposedKey(input)","preventionTips":["Lowercase deposed keys before parsing/display.","Never uppercase hex keys in storage or UI.","Validate with ^[0-9a-f]{8}$ to catch case and charset issues together."],"tags":["addrs","deposed-key","validation","case-sensitivity","terraform"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}