larksuite/cli · error
map type %s requires an explicit Shape
Error message
map type %s requires an explicit Shape
What it means
Map types cannot be given a statically derived schema: their keys and values are not fixed at compile time, so the shape compiler cannot produce an ObjectShape or a constrained value shape. Fields typed as any map are rejected and require an explicit Shape or a concrete struct replacement.
Source
Thrown at shortcuts/common/typed_compile_data.go:165
elementShape, err := shapeForType(baseType.Elem(), elementSchema, input, active)
if err != nil {
return nil, fmt.Errorf("array item: %w", err)
}
shape = typedArrayShape{Items: elementShape, MinItems: schema.minItems, MaxItems: schema.maxItems}
case reflect.Struct:
if implementsCustomEncoding(baseType) {
return nil, fmt.Errorf("custom JSON type %s requires an explicit Shape", baseType)
}
if len(schema.enum) > 0 || hasStringConstraints(schema) || hasNumberConstraints(schema) || hasItemConstraints(schema) || schema.format != "" {
return nil, fmt.Errorf("object field has incompatible schema constraint")
}
object, err := compileStructShape(baseType, input, baseType.String(), active)
if err != nil {
return nil, err
}
shape = object
case reflect.Map:
return nil, fmt.Errorf("map type %s requires an explicit Shape", baseType)
case reflect.Interface:
return nil, fmt.Errorf("interface type %s requires an explicit Shape", baseType)
default:
return nil, fmt.Errorf("Go type %s cannot be mapped to a ValueShape", t)
}
if schema.nullable != nil && *schema.nullable {
shape = typedOneOfShape{Variants: []typedValueShape{shape, typedNullShape{}}}
}
return shape, nil
}
// compileStructShape walks one struct into an ObjectShape. active holds the
// struct types already open on the current recursion path, so a type that
// refers back to itself is reported as a compile error. Without the guard the
// walk never terminates and the goroutine stack is exhausted -- that is a
// fatal runtime error, not a panic, so no recover boundary can contain it and
// the whole CLI dies during command registration.
//View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Define a concrete struct with fixed, json-tagged fields instead of the map.
- Provide an explicit Output.Data.Shape that describes the map's value shape.
- If the content is truly dynamic, make the whole Data type `any` (anyJSONShape) and validate at runtime.
- Encode known key sets as struct fields and keep only genuinely open content out of typed Data.
Example fix
// before
type Data struct {
Labels map[string]string `json:"labels"`
}
// after
type Data struct {
Labels struct {
Env string `json:"env"`
Team string `json:"team"`
} `json:"labels"` Defensive patterns
Strategy: validation
Validate before calling
func hasMapField(t reflect.Type) bool {
for t.Kind() == reflect.Pointer { t = t.Elem() }
switch t.Kind() {
case reflect.Map:
return true
case reflect.Struct:
for i := 0; i < t.NumField(); i++ {
if hasMapField(t.Field(i).Type) { return true }
}
case reflect.Slice, reflect.Array:
return hasMapField(t.Elem())
}
return false
} Type guard
func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } Prevention
- Replace dynamic maps with structs declaring all known keys with json tags.
- Reserve `any` only for top-level Output.Data, not nested fields.
- Validate Data struct types in a registration unit test before merging.
When it happens
Trigger: A Data struct field typed map[string]X, map[string]string, or similar is encountered by shapeForType's reflect.Map case during compileData/collectArgFields.
Common situations: Modeling dynamic key/value bags (labels, metadata, properties); porting from generic JSON code where maps were convenient; OpenAPI additionalProperties-style fields.
Related errors
- json.RawMessage requires an explicit Shape
- byte slice or array %s requires an explicit Shape
- custom JSON type %s requires an explicit Shape
- interface type %s requires an explicit Shape
- Go type %s cannot be mapped to a ValueShape
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/3967be2dba8b24dc.
Report an issue: GitHub.