{"record":{"id":"6f0936a5e4ec5a99","repo":"siyuan-note/siyuan","slug":"field-s-must-not-be-null-decode","errorCode":null,"errorMessage":"Field [%s] must not be null","messagePattern":"Field \\[(.+?)\\] must not be null","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/decode.go","lineNumber":77,"sourceCode":"\t\t\t\treturn fmt.Errorf(\"unsupported embedded request field: %s\", field.Name)\n\t\t\t}\n\t\t\tif err := decodeRequestFields(value.Field(i), fields); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\toptions := \",\" + field.Tag.Get(\"api\") + \",\"\n\t\thas := func(option string) bool { return strings.Contains(options, \",\"+option+\",\") }\n\t\traw, present := fields[name]\n\t\tif !present {\n\t\t\tif has(\"optional\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"Field [%s] is required\", name)\n\t\t}\n\t\tisNull := bytes.Equal(bytes.TrimSpace(raw), []byte(\"null\"))\n\t\tif isNull && !has(\"nullable\") && field.Type.Kind() != reflect.Pointer && !has(\"filterstrings\") {\n\t\t\treturn fmt.Errorf(\"Field [%s] must not be null\", name)\n\t\t}\n\t\tif has(\"filterstrings\") {\n\t\t\tvar entries []json.RawMessage\n\t\t\tif json.Unmarshal(raw, &entries) == nil {\n\t\t\t\tvar ids []string\n\t\t\t\tfor _, entry := range entries {\n\t\t\t\t\tvar id string\n\t\t\t\t\tif !bytes.Equal(bytes.TrimSpace(entry), []byte(\"null\")) && json.Unmarshal(entry, &id) == nil {\n\t\t\t\t\t\tids = append(ids, id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue.Field(i).Set(reflect.ValueOf(ids))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tvar decodeErr error\n\t\tif isNull && has(\"nullable\") {\n\t\t\tvalue.Field(i).SetZero()","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/decode.go#L59-L95","documentation":"When a JSON field is explicitly null and the contract neither marks the field 'nullable' nor 'filterstrings' nor uses a pointer type, decodeRequestFields rejects it. JSON null is treated as a present-but-invalid value distinct from a missing key.","triggerScenarios":"Client sends {\"id\": null} for a field whose type is string/int/struct and whose api tag lacks 'nullable'; serializers emitting null for undefined values; Go/JS objects marshaled with nil fields.","commonSituations":"JavaScript `JSON.stringify({id: someUndefined})` when someUndefined is a null- valued variable; TypeScript interfaces with optional properties typed as T|null; database rows with NULL values passed straight through to the request.","solutions":["Omit the field entirely if it is optional, or send a concrete non-null value","Change the contract field to a pointer type or add `nullable` to its api tag if null is legitimately allowed","Fix client serialization to drop null fields (e.g. omitEmpty / conditional spread)"],"exampleFix":"// before\nfetchPost(url, {id: blockId ?? null})\n// after\nconst body: any = {}\nif (blockId != null) { body.id = blockId }\nfetchPost(url, body)","handlingStrategy":"validation","validationCode":"function dropNulls(obj) {\n  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== null && v !== undefined))\n}\n// fetchPost(path, dropNulls(payload))","typeGuard":"function isNonNull<T>(v: T | null | undefined): v is T { return v !== null && v !== undefined }","tryCatchPattern":"try { await fetchPost(path, payload) } catch (e) { const m = e.message.match(/Field \\[(.+?)\\] must not be null/); if (m) { console.error(`Field \"${m[1]}\" cannot be null — omit it or supply a value`); return } throw e }","preventionTips":["Omit optional fields instead of sending null","Configure serializers to skip null/undefined members","Use pointer or nullable tags in contracts only when null is meaningful","Sanitize data coming from databases/external APIs before building requests"],"tags":["validation","null","api-contract","json"],"backgroundTag":"null-argument","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"}