projectdiscovery/nuclei · error
could not hex decode binary: %s
Error message
could not hex decode binary: %s
What it means
Template compilation error from Matcher.CompileMatchers (pkg/operators/matchers/compile.go:62). For `type: binary` matchers, every `binary:` entry is hex-decoded with hex.DecodeString at compile time; invalid hex (odd length or non-hex characters) returns this error including the offending value. Unlike word matchers' optional 'hex' encoding, binary matchers are strict.
Source
Thrown at pkg/operators/matchers/compile.go:62
// Compile the regexes (with shared cache)
for _, regex := range matcher.Regex {
if cached, err := cache.Regex().GetIFPresent(regex); err == nil && cached != nil {
matcher.regexCompiled = append(matcher.regexCompiled, cached)
continue
}
compiled, err := regexp.Compile(regex)
if err != nil {
return fmt.Errorf("could not compile regex: %s", regex)
}
_ = cache.Regex().Set(regex, compiled)
matcher.regexCompiled = append(matcher.regexCompiled, compiled)
}
// Compile and validate binary Values in matcher
for _, value := range matcher.Binary {
if decoded, err := hex.DecodeString(value); err != nil {
return fmt.Errorf("could not hex decode binary: %s", value)
} else {
matcher.binaryDecoded = append(matcher.binaryDecoded, string(decoded))
}
}
// Compile the dsl expressions (with shared cache)
for _, dslExpression := range matcher.DSL {
if cached, err := cache.DSL().GetIFPresent(dslExpression); err == nil && cached != nil {
matcher.dslCompiled = append(matcher.dslCompiled, cached)
continue
}
compiledExpression, err := govaluate.NewEvaluableExpressionWithFunctions(dslExpression, dsl.HelperFunctions)
if err != nil {
return &dsl.CompilationError{DslSignature: dslExpression, WrappedError: err}
}
_ = cache.DSL().Set(dslExpression, compiledExpression)
matcher.dslCompiled = append(matcher.dslCompiled, compiledExpression)
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Ensure each binary value is an even-length pure hex string: strip spaces/colons/0x, then verify length % 2 == 0
- Verify with a quick shell check: `echo -n '4d5a...' | xxd -r -p | xxd` round-trips
- If the intent is to match literal text, use a word matcher instead of binary
- Validate the template with `nuclei -validate -t template.yaml`
Example fix
# before binary: - '0x4d5a' # after binary: - '4d5a'
Defensive patterns
Strategy: validation
Validate before calling
for _, b := range m.Binary {
if len(b)%2 != 0 { return fmt.Errorf("odd-length hex %q", b) }
for _, c := range b {
if !strings.ContainsRune("0123456789abcdefABCDEF", c) {
return fmt.Errorf("non-hex char %q in %q", c, b)
}
}
} Type guard
func isPureHex(s string) bool {
if len(s)%2 != 0 { return false }
_, err := hex.DecodeString(s)
return err == nil
} Try / catch
if err := m.CompileMatchers(); err != nil && strings.Contains(err.Error(), "could not hex decode binary") {
// strip 0x/spaces from the reported value and re-validate
} Prevention
- Strip separators and 0x prefixes when pasting hex from packet tools
- Always emit even-length lowercase hex when generating templates
- Round-trip check: xxd -r -p | xxd -p
When it happens
Trigger: A binary matcher value with an odd number of hex digits ('4d5'), a '0x' prefix ('0x4d5a'), embedded whitespace, or a raw string pasted where hex was expected.
Common situations: Converting packet signatures/PoC byte sequences to templates and dropping a nibble; pasting 'MZ' style hex with separators (e.g. '4d 5a') or 0x prefixes from Wireshark/ghidra output.
Related errors
- unknown matcher type specified: %s
- could not compile regex: %s
- unknown condition specified: %s
- case-insensitive flag is supported only for 'word' matchers
- matcher %s has unexpected fields: %s
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/4938f811f43972e0.
Report an issue: GitHub.