{"record":{"id":"ccc463c873257a97","repo":"projectdiscovery/katana","slug":"error-decoding-v","errorCode":null,"errorMessage":"error decoding: %v","messagePattern":"error decoding: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/output/output.go","lineNumber":438,"sourceCode":"\t\tgologger.Error().Msgf(\"Could not evaluate DSL expression: %s\\n\", err)\n\t\treturn false\n\t}\n\treturn res == true\n}\n\nfunc resultToMap(result Result) (map[string]interface{}, error) {\n\tresultMap := make(map[string]any)\n\tconfig := &mapstructure.DecoderConfig{\n\t\tTagName: \"json\",\n\t\tResult:  &resultMap,\n\t}\n\tdecoder, err := mapstructure.NewDecoder(config)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating decoder: %v\", err)\n\t}\n\terr = decoder.Decode(result)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error decoding: %v\", err)\n\t}\n\n\trequestMap := make(map[string]any)\n\tif err := mapstructure.Decode(result.Request, &requestMap); err == nil {\n\t\tfor k, v := range requestMap {\n\t\t\tresultMap[strcase.SnakeCase(k)] = v\n\t\t}\n\t}\n\n\tresponseMap := make(map[string]any)\n\tif err := mapstructure.Decode(result.Response, &responseMap); err == nil {\n\t\tfor k, v := range responseMap {\n\t\t\tif strings.ToLower(k) == \"headers\" {\n\t\t\t\tif headers, ok := v.(navigation.Headers); ok {\n\t\t\t\t\tfor hk, hv := range headers {\n\t\t\t\t\t\tresultMap[strcase.SnakeCase(hk)] = hv\n\t\t\t\t\t}\n\t\t\t\t}","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/output/output.go#L420-L456","documentation":"The mapstructure decoder failed to convert the result struct into a map[string]any using its json tags. Decode returns an error when field types are incompatible with the target map (e.g., unsupported kinds) or a field cannot be converted. evalDslExpr then cannot evaluate the expression against the result data.","triggerScenarios":"decoder.Decode(result) hits a result struct field whose value cannot be mapped into map[string]any: nested unexported fields that can't be reflected, circular structures, or incompatible types under json tag naming.","commonSituations":"Matching/extraction results containing custom types without json tags or with func/chan fields; extracting values from a response whose structure changed after an upstream library upgrade; using time.Time or nested pointers the configured decoder can't flatten with the default settings.","solutions":["Read the wrapped %v error to find the exact failing field, then fix that field's type or add a json tag.","Add WeaklyTypedInput: true to DecoderConfig if string/number coercions are the problem.","Ensure all exported fields on the result struct have json tags and no func/chan/circular fields.","Use a custom DecodeHook (e.g., StringToTimeHookFunc) for types mapstructure can't handle natively."],"exampleFix":"// before\nconfig := &mapstructure.DecoderConfig{TagName: \"json\", Result: &resultMap}\n// after\nconfig := &mapstructure.DecoderConfig{\n    TagName:         \"json\",\n    Result:          &resultMap,\n    WeaklyTypedInput: true,\n    DecodeHook:      mapstructure.StringToTimeHookFunc(time.RFC3339),\n}","handlingStrategy":"validation","validationCode":"// ensure result fields are decodable before calling resultToMap\nrv := reflect.ValueOf(result).Elem()\nfor i := 0; i < rv.NumField(); i++ {\n    f := rv.Field(i)\n    if !f.CanInterface() {\n        continue\n    }\n    switch f.Kind() {\n    case reflect.Func, reflect.Chan, reflect.UnsafePointer:\n        return fmt.Errorf(\"field %s is not map-decodable\", rv.Type().Field(i).Name)\n    }\n}","typeGuard":"func isMapDecodable(v any) bool {\n    rv := reflect.ValueOf(v)\n    return rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Struct\n}","tryCatchPattern":"resultMap, err := resultToMap(result)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"error decoding\") {\n        log.Printf(\"result decode failed, evaluating DSL on raw value: %v\", err)\n        resultMap = fallbackRawMap(result)\n    }\n}","preventionTips":["Give every exported result field a json tag and keep types map-friendly (string, number, bool, slices, nested maps).","Add DecodeHookFuncs for time.Time and other special types.","Test DSL evaluation against realistic extraction results, not just primitives."],"tags":["mapstructure","dsl","type-conversion"],"backgroundTag":"struct-to-map-decode-failed","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}