{"record":{"id":"1672cf994eff53bf","repo":"siyuan-note/siyuan","slug":"attribute-view-embedded-base-is-missing","errorCode":null,"errorMessage":"attribute view embedded base is missing","messagePattern":"attribute view embedded base is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/av_union.go","lineNumber":97,"sourceCode":"func avEmbeddedPayloadSchema(b *schemaBuilder, t reflect.Type, input bool) (*Schema, error) {\n\tname := t.Name()\n\tif _, ok := b.definitions[name]; ok {\n\t\treturn &Schema{Ref: \"#/$defs/\" + name}, nil\n\t}\n\tresult := &Schema{}\n\tb.definitions[name] = result\n\tvar base reflect.Type\n\tvar own []reflect.StructField\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tfield := t.Field(i)\n\t\tif field.Anonymous && field.Type.Kind() == reflect.Pointer {\n\t\t\tbase = field.Type.Elem()\n\t\t} else {\n\t\t\town = append(own, field)\n\t\t}\n\t}\n\tif base == nil {\n\t\treturn nil, errors.New(\"attribute view embedded base is missing\")\n\t}\n\tfor _, present := range []bool{true, false} {\n\t\tfields := append([]reflect.StructField{}, own...)\n\t\tif present {\n\t\t\tfor i := 0; i < base.NumField(); i++ {\n\t\t\t\tfield := base.Field(i)\n\t\t\t\tshadowed := false\n\t\t\t\tfor _, child := range own {\n\t\t\t\t\tif child.Name == field.Name {\n\t\t\t\t\t\tshadowed = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !shadowed {\n\t\t\t\t\tfields = append(fields, field)\n\t\t\t\t}\n\t\t\t}\n\t\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/av_union.go#L79-L115","documentation":"avEmbeddedPayloadSchema builds the JSON schema for struct types that must embed exactly one anonymous pointer base type (e.g. *AVLayoutTable). The anonymous pointer field carries the optional inherited fields; if the type registered for schema generation has no such embedded pointer field, the builder cannot model the embedded-present/embedded-absent anyOf and returns this error.","triggerScenarios":"Adding a new struct to the avEmbeddedPayloadSchema switch (or one matching its type list) that lacks an anonymous embedded pointer field, or changing an existing type's embedded field to a named/non-pointer field so the reflect scan finds no candidate.","commonSituations":"Developer defines a new layout wrapper struct and forgets the embedded *AVLayoutXxx base; refactoring flattens the embedding; a type is copied from a non-embedded style and registered in the same schema path.","solutions":["Add an anonymous embedded pointer field (e.g. *AVLayoutTable) to the struct","Verify the struct is registered in the correct schema path (embedded vs regular payload schema)","Regenerate API contracts and run kernel apicontract tests after changing the struct shape"],"exampleFix":"// before\ntype AVViewTableColumn struct {\n    Width int `json:\"width\"`\n}\n// after\ntype AVViewTableColumn struct {\n    *AVLayoutTable\n    Width int `json:\"width\"`\n}","handlingStrategy":"validation","validationCode":"// verify the struct has exactly one anonymous embedded pointer before registering\nfor i := 0; i < t.NumField(); i++ {\n    f := t.Field(i)\n    if f.Anonymous && f.Type.Kind() == reflect.Pointer {\n        fmt.Println(\"embedded base found:\", f.Type.Elem().Name())\n    }\n}","typeGuard":null,"tryCatchPattern":"schema, err := avPayloadSchema(b, t, input)\nif err != nil {\n    return nil, fmt.Errorf(\"build schema for %s: %w\", t.Name(), err)\n}","preventionTips":["Every type in the embedded-schema switch must embed one anonymous pointer base","Run go test ./apicontract/... after adding or reshaping AV structs","Regenerate contract schemas rather than hand-editing them"],"tags":["go","reflection","json-schema","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"}