{"record":{"id":"b247ee396a07c95c","repo":"siyuan-note/siyuan","slug":"view-ids-is-empty","errorCode":null,"errorMessage":"view IDs is empty","messagePattern":"view IDs is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":6996,"sourceCode":"\tfor _, viewID := range viewIDs {\n\t\tif seen[viewID] {\n\t\t\tcontinue\n\t\t}\n\t\tseen[viewID] = true\n\n\t\tview := attrView.GetView(viewID)\n\t\tif nil == view {\n\t\t\treturn fmt.Errorf(\"view [%s] not found\", viewID)\n\t\t}\n\t\tfield := getAttributeViewField(view, keyID)\n\t\tif nil == field {\n\t\t\treturn fmt.Errorf(\"field [%s] not found in view [%s]\", keyID, viewID)\n\t\t}\n\t\tfields = append(fields, field)\n\t}\n\n\tif 1 > len(fields) {\n\t\treturn errors.New(\"view IDs is empty\")\n\t}\n\tfor _, field := range fields {\n\t\tfield.Hidden = hidden\n\t}\n\treturn\n}\n\nfunc getAttributeViewField(view *av.View, keyID string) (ret *av.BaseField) {\n\tswitch view.LayoutType {\n\tcase av.LayoutTypeTable:\n\t\tif nil == view.Table {\n\t\t\treturn\n\t\t}\n\t\tfor _, column := range view.Table.Columns {\n\t\t\tif column.ID == keyID {\n\t\t\t\treturn column.BaseField\n\t\t\t}\n\t\t}","sourceCodeStart":6978,"sourceCodeEnd":7014,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view.go#L6978-L7014","documentation":"The hide/show-fields operation requires at least one resolved field. If the fields list ends up empty — because the viewIDs/keyID inputs produced no valid entries — the kernel rejects the call with this fixed-message error.","triggerScenarios":"Calling the API with an empty viewIDs array, or with inputs whose every entry failed resolution before reaching this check.","commonSituations":"Plugins calling with an empty selection (no views picked); loops filtered out all IDs due to earlier validation; blank/default parameters from unbound UI state.","solutions":["Pass at least one valid view ID in viewIDs","Guard the caller: skip the API call when the selection is empty","Check earlier resolution logic so valid entries are not silently dropped"],"exampleFix":"// before\nif (selectedViews.length) { /* do nothing anyway */ }\nsetAttrViewFieldHidden(avID, [], keyID, hidden)\n// after\nif (!selectedViews.length) return; // guard instead of calling\nsetAttrViewFieldHidden(avID, selectedViews, keyID, hidden)","handlingStrategy":"validation","validationCode":"if (!viewIDs || viewIDs.length === 0) return; // nothing to do, skip the API call","typeGuard":"const hasTargets = (ids: unknown): ids is string[] => Array.isArray(ids) && ids.length > 0;","tryCatchPattern":"try { await setAttrViewFieldHidden(avID, viewIDs, keyID, hidden); } catch (e) { if (String(e).includes(\"view IDs is empty\")) { console.warn(\"no views selected; skipping\"); } else throw e; }","preventionTips":["Guard API calls with non-empty selection checks","Disable the action button when no views are selected","Fail fast in UI code before building the transaction"],"tags":["attribute-view","empty-input","validation"],"backgroundTag":"empty-required-field","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"}