{"record":{"id":"e0a5b49f135e9812","repo":"larksuite/cli","slug":"args-field-s-is-unexported-but-declares-typed-inp","errorCode":null,"errorMessage":"Args field %s is unexported but declares Typed input tags","messagePattern":"Args field (.+?) is unexported but declares Typed input tags","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_args.go","lineNumber":85,"sourceCode":"\t\t\t\treturn nil, nil, fmt.Errorf(\"Args field %s (--%s): alias --%s duplicates %s\", field.goName, field.name, alias.Name, previous)\n\t\t\t}\n\t\t\tallNames[alias.Name] = \"alias of --\" + field.name\n\t\t}\n\t}\n\tif len(supplements) > 0 {\n\t\tfor name := range supplements {\n\t\t\treturn nil, nil, fmt.Errorf(\"Input.Fields references unknown flag --%s\", name)\n\t\t}\n\t}\n\treturn fields, fieldByName, nil\n}\n\nfunc collectArgFields(t reflect.Type, parentIndex []int, insideInline bool, out *[]compiledInputField, seenGo map[string]struct{}, supplements map[string]typedInputField) error {\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tfield := t.Field(i)\n\t\tif !field.IsExported() {\n\t\t\tif hasAnyTag(field, \"flag\", \"arg\", \"schema\", \"cli\", \"doc\", \"json\") {\n\t\t\t\treturn fmt.Errorf(\"Args field %s is unexported but declares Typed input tags\", field.Name)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tflagName, hasFlag := field.Tag.Lookup(\"flag\")\n\t\targMode, hasArg := field.Tag.Lookup(\"arg\")\n\t\tif hasFlag == hasArg {\n\t\t\treturn fmt.Errorf(\"Args field %s must declare exactly one of flag or arg\", field.Name)\n\t\t}\n\t\tif _, duplicate := seenGo[field.Name]; duplicate {\n\t\t\treturn fmt.Errorf(\"Args field %s is duplicated through inline expansion\", field.Name)\n\t\t}\n\t\tseenGo[field.Name] = struct{}{}\n\t\tindex := append(append([]int(nil), parentIndex...), i)\n\t\tif hasArg {\n\t\t\tswitch argMode {\n\t\t\tcase \"local\":\n\t\t\t\tif insideInline {\n\t\t\t\t\treturn fmt.Errorf(\"Args field %s: arg:\\\"local\\\" is not allowed inside inline\", field.Name)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_args.go#L67-L103","documentation":"collectArgFields walks the Args struct via reflection and skips unexported fields, but an unexported field that declares Typed input tags (flag, arg, schema, cli, doc, json) indicates a bug — those tags could never take effect since the field is not settable via reflection. The compiler fails fast with this error instead of silently ignoring the tags.","triggerScenarios":"Declaring a lowercase (unexported) struct field with any of the tags flag, arg, schema, cli, doc, or json in the Args struct and compiling the definition.","commonSituations":"Accidentally lowercasing a field name while adding tags; copying an internal helper field from another struct along with its tags; generating structs where a field was made private but tags remained.","solutions":["Export the field (capitalize its name) if it should be a CLI flag/arg.","Remove the input tags from the unexported field if it is internal state.","Move the value out of Args if it should not be exposed on the command line."],"exampleFix":"// before\ntype Args struct {\n  userID string `flag:\"user-id\" doc:\"user id\"`\n}\n// after\ntype Args struct {\n  // Lark user ID to assign the task.\n  UserID string `flag:\"user-id\"`\n}","handlingStrategy":"validation","validationCode":"func noTaggedUnexported(t reflect.Type) error {\n  for i := 0; i < t.NumField(); i++ {\n    f := t.Field(i)\n    if !f.IsExported() {\n      for _, tag := range []string{\"flag\",\"arg\",\"schema\",\"cli\",\"doc\",\"json\"} {\n        if _, ok := f.Tag.Lookup(tag); ok {\n          return fmt.Errorf(\"unexported field %s has %q tag\", f.Name, tag)\n        }\n      }\n    }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only exported fields may carry input tags — keep Args fields capitalized.","Strip tags when making a field private, or drop it from Args.","Run go vet / struct-tag linters over Args structs."],"tags":["go","reflection","unexported-field","tags"],"backgroundTag":"unexported-field-with-tags","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"}