{"record":{"id":"fa8c2513b8c6dd3c","repo":"golang/go","slug":"malformed-prefix-q-escape-sequence-must-contain","errorCode":null,"errorMessage":"malformed prefix %q: escape sequence must contain two hex digits","messagePattern":"malformed prefix %q: escape sequence must contain two hex digits","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/internal/objabi/path.go","lineNumber":65,"sourceCode":"// PrefixToPath is the inverse of PathToPrefix, replacing escape sequences with\n// the original character.\nfunc PrefixToPath(s string) (string, error) {\n\tpercent := strings.IndexByte(s, '%')\n\tif percent == -1 {\n\t\treturn s, nil\n\t}\n\n\tp := make([]byte, 0, len(s))\n\tfor i := 0; i < len(s); {\n\t\tif s[i] != '%' {\n\t\t\tp = append(p, s[i])\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\t\tif i+2 >= len(s) {\n\t\t\t// Not enough characters remaining to be a valid escape\n\t\t\t// sequence.\n\t\t\treturn \"\", fmt.Errorf(\"malformed prefix %q: escape sequence must contain two hex digits\", s)\n\t\t}\n\n\t\tb, err := strconv.ParseUint(s[i+1:i+3], 16, 8)\n\t\tif err != nil {\n\t\t\t// Not a valid escape sequence.\n\t\t\treturn \"\", fmt.Errorf(\"malformed prefix %q: escape sequence %q must contain two hex digits\", s, s[i:i+3])\n\t\t}\n\n\t\tp = append(p, byte(b))\n\t\ti += 3\n\t}\n\treturn string(p), nil\n}\n","sourceCodeStart":47,"sourceCodeEnd":79,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/internal/objabi/path.go#L47-L79","documentation":"`PrefixToPath` is the inverse of `PathToPrefix` — it decodes `%xx` escape sequences in symbol table names back to their original characters. This specific error fires when a `%` character is found too close to the end of the string: fewer than two characters remain after it, making a complete two-hex-digit escape sequence impossible.","triggerScenarios":"Calling `objabi.PrefixToPath(s)` where `s` contains a `%` in the last one or two positions of the string (e.g., `\"foo%\"` or `\"foo%3\"`). This happens when symbol table names are truncated, corrupted, or manually constructed without valid escaping.","commonSituations":"Corrupt Go object files or archives where symbol names are truncated. Manually splitting or substring-slicing encoded symbol names. A bug in a tool that generates symbol names without using `PathToPrefix`. Reading a truncated or partially-written archive.","solutions":["Ensure the string passed to `PrefixToPath` was generated by `PathToPrefix` and has not been truncated.","If reading from an archive, verify the archive is not corrupt or truncated.","Use `PathToPrefix` consistently for all encoding — do not hand-build `%xx` sequences."],"exampleFix":"// before — manual truncation of encoded name\nprefix := PathToPrefix(\"some/path\")\ntruncated := prefix[:len(prefix)-2]  // may cut a %xx sequence\npath, err := PrefixToPath(truncated)  // fails: trailing % with no digits\n\n// after — preserve full encoded string\npath, err := PrefixToPath(prefix)  // works","handlingStrategy":"validation","validationCode":"// Validate encoded prefix has complete escape sequences before decoding\nfunc validateEncodedPrefix(s string) error {\n    for i := 0; i < len(s); i++ {\n        if s[i] == '%' {\n            if i+2 >= len(s) {\n                return fmt.Errorf(\"incomplete escape at position %d in %q\", i, s)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Decode safely with error handling\nfunc safePrefixToPath(s string) string {\n    path, err := objabi.PrefixToPath(s)\n    if err != nil {\n        return s // fallback to raw string\n    }\n    return path\n}","preventionTips":["Always use PathToPrefix for encoding — never hand-build %xx sequences.","Do not truncate or substring-slice encoded strings between % and its two digits.","Validate string length before decoding if the source is untrusted."],"tags":["path-encoding","symbol-table","escape-sequence","objabi"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}