{"record":{"id":"505d54a98342956c","repo":"siyuan-note/siyuan","slug":"map-string-apicontract-jsonvalue","errorCode":null,"errorMessage":"map[string]apicontract.JSONValue","messagePattern":"map\\[string\\]apicontract\\.JSONValue","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/system_input.go","lineNumber":31,"sourceCode":"\t\tconfig, err := decodeSettingConfig(reader, SystemGetChangelog.Definition().Path, false)\n\t\tif err != nil {\n\t\t\treturn r, nil\n\t\t}\n\t\tr.Force, err = legacyField[bool](config.fields, \"force\", \"Boolean\", false)\n\t\treturn\n\t}\n\tSystemSetUILayout.decodeRequest = func(reader io.Reader) (r SystemUILayoutRequest, err error) {\n\t\tconfig, err := decodeSettingConfig(reader, SystemSetUILayout.Definition().Path, false)\n\t\tif err != nil {\n\t\t\treturn r, err\n\t\t}\n\t\traw := config.fields[\"layout\"]\n\t\tif len(raw) == 0 {\n\t\t\traw = []byte(\"null\")\n\t\t}\n\t\tr.Layout, r.layoutError = legacyJSONValue[map[string]JSONValue](raw)\n\t\tif r.layoutError != nil {\n\t\t\tr.layoutError = errors.New(strings.ReplaceAll(r.layoutError.Error(), \"map[string]apicontract.JSONValue\", \"conf.UILayout\"))\n\t\t}\n\t\treturn\n\t}\n\tSystemLoginAuth.decodeRequest = func(reader io.Reader) (r SystemLoginAuthRequest, err error) {\n\t\tconfig, err := decodeSettingConfig(reader, SystemLoginAuth.Definition().Path, false)\n\t\tif err != nil {\n\t\t\treturn r, err\n\t\t}\n\t\tr.AuthCode, r.authCodeError = legacyField[string](config.fields, \"authCode\", \"String\", true)\n\t\tr.Captcha, r.captchaError = legacyField[string](config.fields, \"captcha\", \"String\", false)\n\t\tr.RememberMe, _ = legacyField[bool](config.fields, \"rememberMe\", \"Boolean\", false)\n\t\treturn\n\t}\n\tSystemOIDCStart.decodeRequest = func(reader io.Reader) (r SystemOIDCStartRequest, err error) {\n\t\tr.parseError = json.NewDecoder(reader).Decode(&r)\n\t\treturn\n\t}\n\tSystemOIDCMobileCallback.decodeRequest = func(reader io.Reader) (r SystemOIDCMobileRequest, err error) {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/system_input.go#L13-L49","documentation":"SystemSetUILayout (/api/system/setUILayout) stores the layout as map[string]JSONValue; this rewritten error surfaces when that map cannot be produced from the `layout` field. The message replaces the internal type name map[string]apicontract.JSONValue with conf.UILayout so the user sees the real config type. It means the `layout` value (or one of its entries) has a shape that does not match the expected UI-layout structure.","triggerScenarios":"POSTing /api/system/setUILayout with layout as a non-object (string/array), or with nested entries whose types conflict during legacy JSON value decoding; an absent layout field decodes as null and is tolerated, so the error comes from an actually present but malformed value.","commonSituations":"A plugin or script persisting a custom layout object that predates the current schema; hand-edited layout JSON with wrong nesting; restoring a layout blob from an older SiYuan version.","solutions":["Send layout as a JSON object matching the conf.UILayout shape (typically {\"<paneID>\":{...layout...}})","Export the current layout via the UI and reuse that structure as a template","If unsure, omit `layout` or send null to reset rather than sending a guessed object"],"exampleFix":"// before\n{\"layout\": \"[{\\\"id\\\":\\\"root\\\"}]\"}\n// after\n{\"layout\": {\"root\": {\"direction\": 1, \"instance\": \"...\"}}}","handlingStrategy":"type-guard","validationCode":"const validLayout = l => l === undefined || l === null || (typeof l === 'object' && !Array.isArray(l));","typeGuard":"const isUILayout = (v) => typeof v === 'object' && (v === null || !Array.isArray(v));","tryCatchPattern":"const res = await fetchPost('/api/system/setUILayout', {layout}); if (res.code !== 0) { /* res.data.layoutError or res.msg describes the field mismatch */ }","preventionTips":["Round-trip layout through the UI export to get a valid shape","Never send a stringified layout object","Send null to reset instead of a guessed structure"],"tags":["json","ui-layout","config","type-mismatch"],"backgroundTag":"config-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"}