{"record":{"id":"91704c8e6a39e356","repo":"siyuan-note/siyuan","slug":"field-preview-should-be-of-type-boolean","errorCode":null,"errorMessage":"Field [preview] should be of type [Boolean]","messagePattern":"Field \\[preview\\] should be of type \\[Boolean\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/template_render.go","lineNumber":30,"sourceCode":"\tMode                                        *string `json:\"mode\" api:\"optional\"`\n\tPreview                                     bool    `json:\"preview\" api:\"optional,nullable\"`\n\tContent                                     *string `json:\"content\" api:\"optional,nonnullable\"`\n\tinvalidMode, invalidPreview, invalidContent bool\n}\n\n// RenderMode 在文档和路径校验后解释模式，显式模式优先于 preview。\nfunc (r RenderTemplateRequest) RenderMode() (string, error) {\n\tif r.invalidMode {\n\t\treturn \"\", fmt.Errorf(\"Unsupported template render mode\")\n\t}\n\tif r.Mode != nil {\n\t\tif *r.Mode != \"preview\" && *r.Mode != \"editorInsert\" {\n\t\t\treturn \"\", fmt.Errorf(\"Unsupported template render mode\")\n\t\t}\n\t\treturn *r.Mode, nil\n\t}\n\tif r.invalidPreview {\n\t\treturn \"\", fmt.Errorf(\"Field [preview] should be of type [Boolean]\")\n\t}\n\tif r.Preview {\n\t\treturn \"preview\", nil\n\t}\n\treturn \"content\", nil\n}\n\nfunc (r RenderTemplateRequest) PreviewSource(mode string) (*string, error) {\n\tif r.invalidContent || (r.Content != nil && mode != \"preview\") {\n\t\treturn nil, fmt.Errorf(\"Source content is only supported for template preview\")\n\t}\n\treturn r.Content, nil\n}\n\ntype TemplatePlanNode struct {\n\tID       string `json:\"id\"`\n\tTitle    string `json:\"title\"`\n\tParentID string `json:\"parentID\"`","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/template_render.go#L12-L48","documentation":"The template render API accepts a `preview` field that must be a JSON boolean. When the request payload carries `preview` with a non-boolean value (string, number, null, object), the request decoder flags it invalid and RenderMode refuses to derive a mode, returning this type error instead of proceeding. It exists to enforce strict request schema typing at the apicontract boundary.","triggerScenarios":"Calling the template render endpoint with body {\"preview\": \"true\"} or {\"preview\": 1} instead of a real JSON boolean; clients serializing booleans as strings; older clients sending truthy numbers.","commonSituations":"Hand-written curl/JSON bodies quoting the boolean; dynamically built payloads in JS where a string 'true' leaks in from a form field; plugin code passing config strings directly into the request.","solutions":["Change the request so preview is an unquoted JSON boolean: true or false","Remove the preview field entirely (the API then falls back to mode \"content\")","Check the client serialization layer so booleans are not stringified before fetch/post","If the value comes from user config, coerce with a strict parser that rejects anything but 'true'/'false' before sending"],"exampleFix":"// before\nPOST body: {\"preview\": \"true\"}\n// after\nPOST body: {\"preview\": true}","handlingStrategy":"validation","validationCode":"function isValidPreviewPayload(body) {\n  return body.preview === undefined || typeof body.preview === \"boolean\";\n}\nif (!isValidPreviewPayload(payload)) throw new Error(\"preview must be a JSON boolean\");","typeGuard":"const isBoolean = (v) => typeof v === \"boolean\";","tryCatchPattern":null,"preventionTips":["Never quote boolean values when hand-writing JSON request bodies","Coerce config-driven flags through a strict boolean parser before sending","Add client-side schema validation (e.g. zod) for request payloads"],"tags":["validation","type-mismatch","api"],"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"}