projectdiscovery/katana · error
error creating decoder: %v
Error message
error creating decoder: %v
What it means
mapstructure.NewDecoder failed while constructing a decoder for converting a result struct into a map using json tags. NewDecoder only errors on invalid DecoderConfig, practically meaning Result is not a non-nil pointer (here &resultMap is always valid), so this is nearly unreachable but defensively handled. If hit, DSL evaluation in evalDslExpr cannot proceed.
Source
Thrown at pkg/output/output.go:434
}
res, err := dsl.EvalExpr(dslExpr, resultMap)
if err != nil && !ignoreErr(err) {
gologger.Error().Msgf("Could not evaluate DSL expression: %s\n", err)
return false
}
return res == true
}
func resultToMap(result Result) (map[string]interface{}, error) {
resultMap := make(map[string]any)
config := &mapstructure.DecoderConfig{
TagName: "json",
Result: &resultMap,
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
return nil, fmt.Errorf("error creating decoder: %v", err)
}
err = decoder.Decode(result)
if err != nil {
return nil, fmt.Errorf("error decoding: %v", err)
}
requestMap := make(map[string]any)
if err := mapstructure.Decode(result.Request, &requestMap); err == nil {
for k, v := range requestMap {
resultMap[strcase.SnakeCase(k)] = v
}
}
responseMap := make(map[string]any)
if err := mapstructure.Decode(result.Response, &responseMap); err == nil {
for k, v := range responseMap {
if strings.ToLower(k) == "headers" {
if headers, ok := v.(navigation.Headers); ok {View on GitHub (pinned to e3e742739c)
Solutions
- Confirm DecoderConfig.Result is a non-nil pointer: Result: &resultMap with resultMap declared as map[string]any.
- Pin/upgrade github.com/mitchellh/mapstructure to a stable version; a broken vendored copy can misbehave.
- Log the underlying error (%v) — it states exactly which config field is invalid.
- If a refactor introduced this, revert the change to the DecoderConfig construction.
Example fix
// before
var resultMap map[string]any
config := &mapstructure.DecoderConfig{TagName: "json", Result: resultMap}
// after
resultMap := make(map[string]any)
config := &mapstructure.DecoderConfig{TagName: "json", Result: &resultMap} Defensive patterns
Strategy: try-catch
Validate before calling
if result == nil || reflect.ValueOf(result).Kind() != reflect.Ptr {
return nil, fmt.Errorf("resultToMap requires a non-nil pointer target")
} Type guard
func isDecoderConfigValid(cfg *mapstructure.DecoderConfig) bool {
return cfg != nil && cfg.Result != nil && reflect.ValueOf(cfg.Result).Kind() == reflect.Ptr && !reflect.ValueOf(cfg.Result).IsNil()
} Try / catch
m, err := resultToMap(result)
if err != nil {
if strings.HasPrefix(err.Error(), "error creating decoder") {
// programmer error in DecoderConfig construction — fail fast with stack trace
}
} Prevention
- Always pass Result as a non-nil pointer to the destination map.
- Keep mapstructure dependency on a pinned, stable version.
- Cover resultToMap with a unit test so DecoderConfig regressions surface in CI.
When it happens
Trigger: resultToMap builds a DecoderConfig and NewDecoder rejects it — only possible if the Result target is nil or not a pointer, which would require resultMap to be nil or the config struct corrupted.
Common situations: Practically never seen in production; encountered when refactoring resultToMap (e.g., passing a nil map pointer or removing the & on Result) or when a vendored/patched mapstructure version has stricter config validation.
Related errors
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/46d36ee2cbd01637.
Report an issue: GitHub.