{"record":{"id":"177849230ad35c14","repo":"siyuan-note/siyuan","slug":"entry-s-w","errorCode":null,"errorMessage":"entry [%s]: %w","messagePattern":"entry \\[(.+?)\\]: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/decode.go","lineNumber":205,"sourceCode":"\t\t\treturn err\n\t\t}\n\t\tvalue.Set(reflect.MakeSlice(value.Type(), len(entries), len(entries)))\n\t\tfor i, entry := range entries {\n\t\t\tif err := decodeRequestValue(entry, value.Index(i)); err != nil {\n\t\t\t\treturn fmt.Errorf(\"element [%d]: %w\", i, err)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase reflect.Map:\n\t\tvar entries map[string]json.RawMessage\n\t\tif err := json.Unmarshal(raw, &entries); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvalue.Set(reflect.MakeMapWithSize(value.Type(), len(entries)))\n\t\tfor key, entry := range entries {\n\t\t\tchild := reflect.New(value.Type().Elem()).Elem()\n\t\t\tif err := decodeRequestValue(entry, child); err != nil {\n\t\t\t\treturn fmt.Errorf(\"entry [%s]: %w\", key, err)\n\t\t\t}\n\t\t\tvalue.SetMapIndex(reflect.ValueOf(key).Convert(value.Type().Key()), child)\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn json.Unmarshal(raw, value.Addr().Interface())\n\t}\n}\n","sourceCodeStart":187,"sourceCodeEnd":214,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/decode.go#L187-L214","documentation":"When decoding a JSON object into a map-typed contract field, decodeRequestValue wraps any failure for a specific key as \"entry [%s]: %w\" with the offending key name. It means one value inside the map failed the strict decoder for the map's element type. The wrapped cause from the recursive decode is preserved.","triggerScenarios":"Sending a map field (e.g. kramdown doc mapping, custom attribute maps) where one entry's value does not decode into the map's value type — e.g. {\"key\": null} for a map[string]string field, or nested wrong types.","commonSituations":"Building maps dynamically in JavaScript where a value ended up null/undefined; sending attributes objects with mixed value types; version drift where the contract narrowed the map value type.","solutions":["Fix the entry named in the error so its value matches the map's declared value type","Omit invalid entries from the map before sending","Coerce values client-side (String(v), Boolean(v)) to the expected type","Verify the map value type in the endpoint's contract definition"],"exampleFix":"// before\nattrs: { \"name\": \"a\", \"memo\": null }\n// after\nattrs: { \"name\": \"a\", \"memo\": \"\" }","handlingStrategy":"validation","validationCode":"function validateMap(obj, check) {\n  for (const [k, v] of Object.entries(obj)) { if (!check(v)) throw new Error(`entry [${k}] invalid`); }\n}\nvalidateMap(payload.attrs, (v) => typeof v === \"string\");","typeGuard":"const allValuesOfType = (o, t) => Object.values(o).every((v) => typeof v === t);","tryCatchPattern":"try { await fetchPost(url, payload); } catch (e) { const m = String(e).match(/entry \\[([^\\]]+)]/); if (m) console.error(\"Bad map entry:\", m[1]); }","preventionTips":["Validate map values before sending","Never put undefined/null into dynamically built maps","Coerce values to the declared map value type first","Keep map builders strongly typed in TypeScript"],"tags":["api","json","map","validation"],"backgroundTag":"type-mismatch","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}