{"record":{"id":"74e6d4eefd20d2c5","repo":"larksuite/cli","slug":"postmount-modified-typed-flag-s-or-its-input-an","errorCode":null,"errorMessage":"PostMount modified Typed flag --%s or its input annotations","messagePattern":"PostMount modified Typed flag --(.+?) or its input annotations","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_mount_guard.go","lineNumber":99,"sourceCode":"\t\tseen[name] = struct{}{}\n\t\tnames = append(names, name)\n\t}\n\tfor name := range after.flags {\n\t\tif _, ok := seen[name]; !ok {\n\t\t\tnames = append(names, name)\n\t\t}\n\t}\n\tsort.Strings(names)\n\tfor _, name := range names {\n\t\tbeforeFlag, existedBefore := before.flags[name]\n\t\tafterFlag, existsAfter := after.flags[name]\n\t\tswitch {\n\t\tcase !existedBefore:\n\t\t\treturn fmt.Errorf(\"PostMount added undeclared Typed flag --%s\", name)\n\t\tcase !existsAfter:\n\t\t\treturn fmt.Errorf(\"PostMount removed Typed flag --%s\", name)\n\t\tcase !reflect.DeepEqual(beforeFlag, afterFlag):\n\t\t\treturn fmt.Errorf(\"PostMount modified Typed flag --%s or its input annotations\", name)\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":81,"sourceCodeEnd":104,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_mount_guard.go#L81-L104","documentation":"Thrown by validateTypedPostMount when a flag declared during mount still exists after PostMount but differs from its declared definition — value type, default, usage text, shorthand, NoOptDefVal, deprecated status, hidden state, or flag annotations changed. Typed mounts treat the declared flag set (including input annotations) as an immutable contract, so PostMount may not alter it.","triggerScenarios":"A PostMount hook calls flag.Usage = ..., cmd.Flags().Lookup(name).DefValue mutation, MarkHidden, MarkDeprecated, SetAnnotation, or changes Shorthand/NoOptDefVal on any Typed-declared flag.","commonSituations":"Developers customizing help output or hiding flags for internal commands in PostMount; changing usage strings centrally; or annotating flags with input metadata inside PostMount instead of declaring it in the Typed input definition.","solutions":["Move any flag metadata (usage, hidden, deprecated, annotations, shorthand) into the Typed flag declaration in the shortcut definition, not the PostMount hook.","If the flag needs a different default or type, change the declared Typed definition, not runtime state in PostMount.","Search the PostMount hook for calls like MarkHidden, MarkDeprecated, SetAnnotation, or direct Lookup(...).Field assignments and delete them."],"exampleFix":"// before (PostMount hook)\nfunc (h *hook) PostMount(cmd *cobra.Command) error {\n    f := cmd.Flags().Lookup(\"chat_id\")\n    f.Usage = \"custom usage\" // modifies declared flag\n    return nil\n}\n// after: declare it at mount time\nflags: []command.Flag{{ Name: \"chat_id\", Usage: \"custom usage\", /* ... */ }}","handlingStrategy":"validation","validationCode":"// Snapshot-compare in a unit test, mirroring the guard:\nwant := \"Custom usage for chat\"\ncmd.SetArgs([]string{\"--help\"})\nif f := cmd.Flags().Lookup(\"chat_id\"); f == nil || f.Usage != want {\n    t.Fatalf(\"declared flag chat_id changed; declare metadata at mount time\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call MarkHidden, MarkDeprecated, SetAnnotation, or mutate Lookup results inside PostMount.","Review hooks with a checklist: no flag set mutation, no metadata writes.","Rely on mountDeclarative's guard tests; add dry-run E2E for every shortcut change so the guard runs in CI."],"tags":["cli","flags","registration","postmount","guard"],"backgroundTag":"postmount-flag-mutation-forbidden","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"}