{"record":{"id":"04a6a95d93d3dcad","repo":"siyuan-note/siyuan","slug":"field-id-must-not-be-empty-graph-query","errorCode":null,"errorMessage":"Field [id] must not be empty","messagePattern":"Field \\[id\\] must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/graph_query.go","lineNumber":161,"sourceCode":"\t\trequest.ReqID = reqID\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\terr = &graphQueryDecodeError{reqID, err}\n\t\t\t}\n\t\t}()\n\t\tif len(fields[\"id\"]) == 0 || bytes.Equal(bytes.TrimSpace(fields[\"id\"]), []byte(\"null\")) {\n\t\t\treturn request, nil\n\t\t}\n\t\tif request.K, err = legacyField[string](fields, \"k\", \"String\", false); err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tid, err := legacyField[string](fields, \"id\", \"String\", true)\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tid = strings.TrimSpace(id)\n\t\tif id == \"\" {\n\t\t\treturn request, fmt.Errorf(\"Field [id] must not be empty\")\n\t\t}\n\t\trequest.ID = &id\n\t\tconfiguration, err := decodeGraphConfiguration(fields)\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\trequest.Conf = configuration\n\t\tif raw, exists := fields[\"notebook\"]; exists {\n\t\t\t_ = json.Unmarshal(raw, &request.Notebook)\n\t\t}\n\t\treturn\n\t}\n\tGetGraph.decodeFailure = func(err error) Response[GlobalGraphData] {\n\t\tvar failure *graphQueryDecodeError\n\t\tif errors.As(err, &failure) {\n\t\t\treturn GetGraph.FailureWithData(-1, err.Error(), GraphQueryEcho[GlobalGraphResult](failure.reqID))\n\t\t}\n\t\treturn Failure[GlobalGraphData](-1, err.Error())","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/graph_query.go#L143-L179","documentation":"The graph query decoder reads the `id` field as a required String via legacyField, trims it, and rejects an empty result. The identifier selects which graph configuration the query targets, so an empty id is meaningless and rejected with 'Field [id] must not be empty'.","triggerScenarios":"Sending a graph query with \"id\": \"\" or \"id\": \"   \"; a missing id surfaces as 'Field [id] is required' from legacyField instead, so this message specifically means present-but-blank.","commonSituations":"Client code reading the graph id from a variable that was never populated; UI code passing an empty selection when no graph tab is active.","solutions":["Provide a valid non-empty id, e.g. {\"id\": \"local\"}","Guard the caller: skip the API call when the id is empty","Verify the value is not whitespace-only after trimming"],"exampleFix":"// before\n{\"id\": \"\", \"conf\": {}}\n// after\n{\"id\": \"local\", \"conf\": {}}","handlingStrategy":"type-guard","validationCode":"const graphId = getSelectedGraphId();\nif (!graphId || graphId.trim() === \"\") {\n  return; // skip API call until a graph id is known\n}","typeGuard":"const isValidId = (v) => typeof v === \"string\" && v.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Guard UI handlers so they no-op when no graph is selected","Never send ids derived from possibly-empty state without checking"],"tags":["api","validation","empty-value","identifier"],"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"}