{"record":{"id":"7e08413f83882441","repo":"siyuan-note/siyuan","slug":"attribute-view-response-variant-is-not-set","errorCode":null,"errorMessage":"attribute view response variant is not set","messagePattern":"attribute view response variant is not set","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"kernel/apicontract/av_union.go","lineNumber":141,"sourceCode":"}\n\ntype AVRenderResult struct {\n\tsuccess *AVRenderData\n\tfailure *AVViewNotFound\n}\n\nfunc NewAVRenderResult(value AVRenderData) AVRenderResult { return AVRenderResult{success: &value} }\nfunc NewAVRenderResultError(value AVViewNotFound) AVRenderResult {\n\treturn AVRenderResult{failure: &value}\n}\nfunc (value AVRenderResult) MarshalJSON() ([]byte, error) {\n\tif value.success != nil {\n\t\treturn json.Marshal(value.success)\n\t}\n\tif value.failure != nil {\n\t\treturn json.Marshal(value.failure)\n\t}\n\treturn nil, errors.New(\"attribute view response variant is not set\")\n}\n\ntype AVCreateItemResult struct {\n\tsuccess *AVCreateAttributeViewItemResult\n\tfailure *AVUnavailableNotebook\n}\n\nfunc NewAVCreateItemResult(value AVCreateAttributeViewItemResult) AVCreateItemResult {\n\treturn AVCreateItemResult{success: &value}\n}\nfunc NewAVCreateItemResultError(value AVUnavailableNotebook) AVCreateItemResult {\n\treturn AVCreateItemResult{failure: &value}\n}\nfunc (value AVCreateItemResult) MarshalJSON() ([]byte, error) {\n\tif value.success != nil {\n\t\treturn json.Marshal(value.success)\n\t}\n\tif value.failure != nil {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/av_union.go#L123-L159","documentation":"AVRenderResult is a success/failure union (AVRenderData or AVViewNotFound); MarshalJSON emits whichever pointer is set. If both are nil (zero value or forgotten constructor), serialization fails with this error so an ambiguous empty response is never produced.","triggerScenarios":"Returning AVRenderResult{} from a handler, or constructing it via a struct literal without NewAVRenderResult/NewAVRenderResultError; surfaces when rendering an attribute view whose result was never initialized.","commonSituations":"Early-return paths added after the result variable is declared; error checks that skip both constructors; zero-value struct returned by a helper function.","solutions":["Always build the result with NewAVRenderResult or NewAVRenderResultError","Return a AVViewNotFound failure variant instead of an empty value when data is unavailable","Add a unit test covering every handler return path so zero unions fail in CI"],"exampleFix":"// before\nvar result apicontract.AVRenderResult\nreturn result\n// after\nreturn apicontract.NewAVRenderResultError(apicontract.AVViewNotFound{...})","handlingStrategy":"validation","validationCode":"func checkRenderResult(r apicontract.AVRenderResult) error {\n    if r.Marshalable() { return nil }\n    return errors.New(\"AVRenderResult built without NewAVRenderResult/Error\")\n}","typeGuard":"func isRenderResultSet(r apicontract.AVRenderResult) bool {\n    return r.Success() != nil || r.Failure() != nil\n}","tryCatchPattern":"payload, err := json.Marshal(result)\nif err != nil {\n    http.Error(w, \"internal response error\", http.StatusInternalServerError)\n    return\n}","preventionTips":["Always construct with NewAVRenderResult / NewAVRenderResultError","Never return a declared-but-unassigned result variable","In error paths, return the failure variant instead of zero value"],"tags":["go","json-marshal","union-type","attribute-view"],"backgroundTag":"internal-invariant-violation","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"}