{"record":{"id":"76c7ebeff1303ed1","repo":"siyuan-note/siyuan","slug":"field-assets-d-should-be-of-type-object","errorCode":null,"errorMessage":"Field [assets.%d] should be of type [Object]","messagePattern":"Field \\[assets\\.(.+?)\\] should be of type \\[Object\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/clipboard_input.go","lineNumber":28,"sourceCode":"\nfunc init() {\n\tPrepareRichText.decodeRequest = func(reader io.Reader) (request PrepareRichTextRequest, err error) {\n\t\tfields, err := blockRequestFields(reader, \"/api/clipboard/prepareRichText\")\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tassets, err := legacyField[[]json.RawMessage](fields, \"assets\", \"Array\", true)\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tif len(assets) == 0 {\n\t\t\treturn request, fmt.Errorf(\"Field [assets] must not be empty\")\n\t\t}\n\t\trequest.Assets = make([]RichClipboardAsset, 0, len(assets))\n\t\tfor i, raw := range assets {\n\t\t\tvar asset map[string]json.RawMessage\n\t\t\tif json.Unmarshal(raw, &asset) != nil || asset == nil {\n\t\t\t\treturn request, fmt.Errorf(\"Field [assets.%d] should be of type [Object]\", i)\n\t\t\t}\n\t\t\tvar index float64\n\t\t\tvar path, box string\n\t\t\tif bytes.Equal(asset[\"index\"], []byte(\"null\")) || json.Unmarshal(asset[\"index\"], &index) != nil || index < 0 || index != float64(int(index)) || json.Unmarshal(asset[\"path\"], &path) != nil || strings.TrimSpace(path) == \"\" {\n\t\t\t\treturn request, fmt.Errorf(\"Invalid rich clipboard asset at index [%d]\", i)\n\t\t\t}\n\t\t\tif value, exists := asset[\"box\"]; exists {\n\t\t\t\tif bytes.Equal(value, []byte(\"null\")) || json.Unmarshal(value, &box) != nil {\n\t\t\t\t\treturn request, fmt.Errorf(\"Field [assets.%d.box] should be of type [String]\", i)\n\t\t\t\t}\n\t\t\t}\n\t\t\trequest.Assets = append(request.Assets, RichClipboardAsset{Index: int(index), Path: strings.TrimSpace(path), Box: strings.TrimSpace(box)})\n\t\t}\n\t\treturn\n\t}\n\tCleanupRichText.decodeRequest = func(reader io.Reader) (request CleanupRichTextRequest, err error) {\n\t\tfields, err := blockRequestFields(reader, \"/api/clipboard/cleanupRichText\")\n\t\tif err != nil {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/clipboard_input.go#L10-L46","documentation":"Each element of the assets array in /api/clipboard/prepareRichText must be a JSON object. This error fires when an element fails to unmarshal into an object (e.g. it is a string, number, or array) or unmarshals to a nil map.","triggerScenarios":"Sending assets: [\"foo\"], [123], [[]], or [null] to /api/clipboard/prepareRichText instead of an array of objects like [{\"index\":0,\"path\":\"...\"}].","commonSituations":"Serializing asset IDs/paths directly instead of asset objects; a JSON producer double-encoding assets as strings; mixing old string-based asset payloads with the newer object schema after an API version change.","solutions":["Send each asset as an object with at least a non-negative integer index and a non-empty string path","Validate the payload shape before sending (typeof item === 'object' && !Array.isArray(item))","Check for double JSON encoding — a JSON-stringified object inside the array will arrive as a string"],"exampleFix":"// before\n{assets: [\"/assets/foo.png\"]}\n// after\n{assets: [{index: 0, path: \"/assets/foo.png\"}]}","handlingStrategy":"type-guard","validationCode":"assets.forEach((a, i) => { if (typeof a !== 'object' || a === null || Array.isArray(a)) throw new Error(`assets[${i}] must be an object`); });","typeGuard":"const isAssetObject = (a) => typeof a === 'object' && a !== null && !Array.isArray(a);","tryCatchPattern":null,"preventionTips":["Never JSON.stringify elements inside the array (double encoding)","Construct assets with an explicit builder function","Diff payload shape against docs/API-CONTRACTS.md after upgrades"],"tags":["validation","type-mismatch","clipboard"],"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"}