{"record":{"id":"5438178f1854f1a8","repo":"siyuan-note/siyuan","slug":"unsupported-embedded-request-field-s","errorCode":null,"errorMessage":"unsupported embedded request field: %s","messagePattern":"unsupported embedded request field: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/decode.go","lineNumber":59,"sourceCode":"\t}\n\tvalue := reflect.ValueOf(&request).Elem()\n\tif value.Kind() != reflect.Struct {\n\t\treturn request, fmt.Errorf(\"request contract must be a struct\")\n\t}\n\terr = decodeRequestFields(value, fields)\n\treturn request, err\n}\n\nfunc decodeRequestFields(value reflect.Value, fields map[string]json.RawMessage) error {\n\tfor i := 0; i < value.NumField(); i++ {\n\t\tfield := value.Type().Field(i)\n\t\tname := strings.Split(field.Tag.Get(\"json\"), \",\")[0]\n\t\tif (!field.IsExported() && !field.Anonymous) || name == \"-\" {\n\t\t\tcontinue\n\t\t}\n\t\tif field.Anonymous && name == \"\" {\n\t\t\tif field.Type.Kind() != reflect.Struct {\n\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)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/decode.go#L41-L77","documentation":"decodeRequestFields walks the request struct's fields; anonymous (embedded) fields with no JSON name must be structs so they can be recursed into. An embedded non-struct (e.g. an embedded string, int, or interface) cannot be flattened, so this error names the offending field. It indicates an unsupported contract shape.","triggerScenarios":"Embedding a non-struct type (embedded string, embedded interface, embedded map) in a request contract struct without a json tag name.","commonSituations":"Embedding a type alias like `type ID string` directly; embedding time.Duration or another named primitive; auto-generating contracts from types with primitive embeds.","solutions":["Give the embedded field an explicit json name instead of embedding it","Change the embedded type to a struct, or wrap the primitive in a named field","Restructure the request contract so all anonymous fields are structs"],"exampleFix":"// before\ntype Req struct {\n\tBase\n\tstring // anonymous non-struct embed\n}\n// after\ntype Req struct {\n\tBase\n\tNote string `json:\"note\"`\n}","handlingStrategy":"validation","validationCode":"func validateContractShape(v reflect.Value) error { t := v.Type(); for i := 0; i < t.NumField(); i++ { f := t.Field(i); if f.Anonymous && strings.Split(f.Tag.Get(\"json\"), \",\")[0] == \"\" && f.Type.Kind() != reflect.Struct { return fmt.Errorf(\"embedded field %s must be a struct\", f.Name) } }; return nil }","typeGuard":"func embeddable(f reflect.StructField) bool { return !f.Anonymous || strings.Split(f.Tag.Get(\"json\"), \",\")[0] != \"\" || f.Type.Kind() == reflect.Struct }","tryCatchPattern":"if err := decodeRequestFields(value, fields); err != nil { if strings.HasPrefix(err.Error(), \"unsupported embedded request field\") { return fmt.Errorf(\"fix contract struct shape: %w\", err) }; return err }","preventionTips":["Only embed structs anonymously in request contracts","Give non-struct helper fields explicit json names","Lint contract structs at build time for anonymous non-struct fields"],"tags":["reflection","json-tags","api-contract","schema"],"backgroundTag":"schema-validation-failed","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"}