larksuite/cli · error
%s field %s must declare json tag
Error message
%s field %s must declare json tag
What it means
This error comes from the typed shortcut data compiler when building an object shape from a struct. Every exported struct field must carry an explicit `json` tag so the compiler knows the wire name; a field without one makes the compiled schema ambiguous. The compiler refuses to guess a field name, so it fails at compile time of the type registration.
Source
Thrown at shortcuts/common/typed_compile_data.go:203
// removed once its fields are compiled, so the same type appearing twice as a
// sibling stays legal.
func compileStructShape(t reflect.Type, input bool, path string, active map[reflect.Type]struct{}) (typedObjectShape, error) {
if _, cyclic := active[t]; cyclic {
return typedObjectShape{}, fmt.Errorf("recursive type %s requires an explicit Shape", t)
}
active[t] = struct{}{}
defer delete(active, t)
shape := typedObjectShape{}
seen := make(map[string]string)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.IsExported() {
continue
}
rawJSON, ok := field.Tag.Lookup("json")
if !ok {
return typedObjectShape{}, fmt.Errorf("%s field %s must declare json tag", path, field.Name)
}
parts := strings.Split(rawJSON, ",")
name := parts[0]
if name == "-" {
continue
}
if name == "" {
return typedObjectShape{}, fmt.Errorf("%s field %s json tag must explicitly name the field", path, field.Name)
}
omitempty := false
for _, option := range parts[1:] {
switch option {
case "omitempty":
omitempty = true
case "":
default:
return typedObjectShape{}, fmt.Errorf("%s field %s has unsupported json option %q", path, field.Name, option)
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Add an explicit `json` tag to the named field, e.g. `json:"fieldName"`
- Use `json:"-"` if the field is internal and should be excluded from the shape (it is then skipped)
- If the field should not be part of the schema at all, make it unexported
Example fix
// before
type Input struct {
Name string
}
// after
type Input struct {
Name string `json:"name" schema:"required" doc:"Display name"`
} Defensive patterns
Strategy: validation
Validate before calling
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.IsExported() {
if _, ok := f.Tag.Lookup("json"); !ok {
return fmt.Errorf("field %s needs a json tag", f.Name)
}
}
} Prevention
- Add json tags immediately when writing any exported struct field
- Add a unit test that compiles all registered typed structs early
- Make linters (e.g. exhaustive/json tag linters) enforce tags in CI
When it happens
Trigger: Registering a struct with compileData/shapeForType where an exported field has no `json` tag at all, e.g. `Name string` without `json:"name"`.
Common situations: Adding a new field to an existing typed Data/Input struct and forgetting the tag; copying a struct from non-JSON code (internal models) into a typed shortcut definition; embedding types whose fields were previously serialized by other means.
Related errors
- %s field %s json tag must explicitly name the field
- %s field %s has unsupported json option %q
- %s field %s JSON name %q duplicates field %s
- %s field %s (%s): description is required via doc
- ErrMalformedConfig
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/a14c3e4c5022d062.
Report an issue: GitHub.