{"record":{"id":"534e3c9db1fb7b48","repo":"larksuite/cli","slug":"hooks-renderers-q-is-nil","errorCode":null,"errorMessage":"Hooks.Renderers[%q] is nil","messagePattern":"Hooks\\.Renderers\\[%q\\] is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_output.go","lineNumber":21,"sourceCode":"\n//nolint:forbidigo // Compiler diagnostics are build-time declaration errors wrapped by the command-set startup guard.\npackage common\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\nfunc validateOutputHooks(definition typedOutputDefinition, renderers map[string]rendererMarker) error {\n\trendererNames := make([]string, 0, len(renderers))\n\tfor name := range renderers {\n\t\trendererNames = append(rendererNames, name)\n\t}\n\tsort.Strings(rendererNames)\n\tfor _, name := range rendererNames {\n\t\trenderer := renderers[name]\n\t\tif renderer.isNil {\n\t\t\treturn fmt.Errorf(\"Hooks.Renderers[%q] is nil\", name)\n\t\t}\n\t\tif name != \"pretty\" {\n\t\t\treturn fmt.Errorf(\"Hooks.Renderers[%q] is invalid: custom renderers are only supported for pretty; table, csv, and ndjson use framework formatters\", name)\n\t\t}\n\t\tif definition.Mode == typedOutputFixedJSON {\n\t\t\treturn fmt.Errorf(\"Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSON output does not execute custom renderers\", name, definition.Mode)\n\t\t}\n\t}\n\treturn nil\n}\n\n// rendererMarker lets the bridge compiler inspect nil renderer values without\n// exposing the private compiled hook type.\ntype rendererMarker struct{ isNil bool }\n","sourceCodeStart":3,"sourceCodeEnd":36,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_output.go#L3-L36","documentation":"validateOutputHooks inspects every entry in Hooks.Renderers via a rendererMarker that detects nil values without exposing the private hook type. A map entry whose value is a nil (typed-nil) custom renderer cannot be invoked, so the compiler rejects the definition at startup. Registering a renderer requires a non-nil callable value.","triggerScenarios":"CompileCommandDefinition (or the typed bridge) called with Hooks.Renderers containing a key mapped to a nil func value, e.g. map[string]any{\"pretty\": nil} or a typed nil function variable that was never assigned.","commonSituations":"Declaring the renderer key but forgetting to assign the function; a variable of function type that is nil until some init code runs (and never does); conditional assignment skipped in tests or feature-flagged builds.","solutions":["Assign a real renderer function for the key in Hooks.Renderers.","Delete the map entry if no custom renderer is needed (absence is valid; nil is not).","Check initializer order/conditions that leave the renderer variable nil at compile time."],"exampleFix":"// before\nHooks: common.Hooks{Renderers: map[string]common.Renderer{\"pretty\": nil}}\n// after\nHooks: common.Hooks{Renderers: map[string]common.Renderer{\"pretty\": func(v any, opts common.RenderOptions) (string, error) { ... }}}","handlingStrategy":"type-guard","validationCode":"func checkRenderers(r map[string]common.Renderer) error {\n  for name, fn := range r {\n    if fn == nil { return fmt.Errorf(\"renderer %q is nil\", name) }\n  }\n  return nil\n}","typeGuard":"func rendererSet(r map[string]common.Renderer, name string) bool { return r != nil && r[name] != nil }","tryCatchPattern":null,"preventionTips":["Never pre-declare renderer keys with nil placeholders; add the entry only when the function exists.","Avoid function-typed variables that may remain nil; use function literals inline.","Check hooks structs for typed-nil functions before passing them to the compiler."],"tags":["hooks","nil","compile-time"],"backgroundTag":"nil-callback","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"}