{"record":{"id":"a6cfa1d58e442b5d","repo":"larksuite/cli","slug":"s-field-s-s-nil-capable-field-must-declare-n","errorCode":null,"errorMessage":"%s field %s (%s): nil-capable field must declare nullable or nonnullable","messagePattern":"(.+?) field (.+?) \\((.+?)\\): nil-capable field must declare nullable or nonnullable","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_data.go","lineNumber":241,"sourceCode":"\t\tif previous, exists := seen[name]; exists {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s JSON name %q duplicates field %s\", path, field.Name, name, previous)\n\t\t}\n\t\tseen[name] = field.Name\n\t\tschema, err := parseSchemaTag(field.Tag.Get(\"schema\"), field.Type, input)\n\t\tif err != nil {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): %w\", path, field.Name, name, err)\n\t\t}\n\t\tif !input && schema.defaultValue.Set {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): Data field cannot declare default\", path, field.Name, name)\n\t\t}\n\t\tif schema.required && omitempty {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): required Data field cannot use omitempty\", path, field.Name, name)\n\t\t}\n\t\tif schema.optional && !omitempty {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): optional Data field must use omitempty\", path, field.Name, name)\n\t\t}\n\t\tif isNilCapable(field.Type) && schema.nullable == nil {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): nil-capable field must declare nullable or nonnullable\", path, field.Name, name)\n\t\t}\n\t\tdescription := strings.TrimSpace(field.Tag.Get(\"doc\"))\n\t\tif input && description == \"\" {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): description is required via doc\", path, field.Name, name)\n\t\t}\n\t\tfieldShape, err := shapeForType(field.Type, schema, input, active)\n\t\tif err != nil {\n\t\t\treturn typedObjectShape{}, fmt.Errorf(\"%s field %s (%s): %w\", path, field.Name, name, err)\n\t\t}\n\t\tshape.Fields = append(shape.Fields, typedValueField{Name: name, Description: description, Required: schema.required, Shape: fieldShape})\n\t}\n\treturn shape, nil\n}\n\nfunc validateShape(shape typedValueShape, path string) error {\n\tif shape == nil {\n\t\treturn fmt.Errorf(\"%s is nil\", path)\n\t}","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_data.go#L223-L259","documentation":"A field whose Go type can hold nil (pointer, slice, map, interface, etc.) must explicitly state whether null is an accepted/produced value via a `nullable` or `nonnullable` schema option. The compiler refuses to guess nil semantics, so the compiled schema is unambiguous for consumers.","triggerScenarios":"Compiling a struct where e.g. `*string`, `[]Item`, or `map[string]string` field has no `nullable`/`nonnullable` option in its `schema:` tag, via compileStructShape.","commonSituations":"Introducing a pointer field for optionality without updating the schema tag; changing a value type to a pointer during refactor; maps/slices added for dynamic payloads.","solutions":["Add `nullable` to the schema tag if null is allowed, e.g. `schema:\"optional,nullable\"`","Add `nonnullable` if nil is never valid (compiler/enforcement then guards that)","Use a non-nil-capable type if the field can never be absent"],"exampleFix":"// before\nOwner *string `json:\"owner,omitempty\" schema:\"optional\" doc:\"...\"`\n// after\nOwner *string `json:\"owner,omitempty\" schema:\"optional,nullable\" doc:\"...\"`","handlingStrategy":"validation","validationCode":"if isNilCapable(f.Type) {\n    s := f.Tag.Get(\"schema\")\n    if !strings.Contains(s, \"nullable\") && !strings.Contains(s, \"nonnullable\") {\n        return fmt.Errorf(\"field %s: nil-capable type must declare nullable/nonnullable\", f.Name)\n    }\n}","typeGuard":"func isNilCapable(t reflect.Type) bool {\n    switch t.Kind() {\n    case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface, reflect.Chan, reflect.Func:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Treat every pointer/slice/map field as requiring a nullability decision at authoring time","Prefer value types with required schema when null is impossible","Add the nullable keyword in the same commit that introduces the pointer field"],"tags":["go","struct-tags","schema","nullable","pointers"],"backgroundTag":"missing-nullable-declaration","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}