larksuite/cli · error
Hooks.Renderers[%q] is nil
Error message
Hooks.Renderers[%q] is nil
What it means
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.
Source
Thrown at shortcuts/common/typed_compile_output.go:21
//nolint:forbidigo // Compiler diagnostics are build-time declaration errors wrapped by the command-set startup guard.
package common
import (
"fmt"
"sort"
)
func validateOutputHooks(definition typedOutputDefinition, renderers map[string]rendererMarker) error {
rendererNames := make([]string, 0, len(renderers))
for name := range renderers {
rendererNames = append(rendererNames, name)
}
sort.Strings(rendererNames)
for _, name := range rendererNames {
renderer := renderers[name]
if renderer.isNil {
return fmt.Errorf("Hooks.Renderers[%q] is nil", name)
}
if name != "pretty" {
return fmt.Errorf("Hooks.Renderers[%q] is invalid: custom renderers are only supported for pretty; table, csv, and ndjson use framework formatters", name)
}
if definition.Mode == typedOutputFixedJSON {
return fmt.Errorf("Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSON output does not execute custom renderers", name, definition.Mode)
}
}
return nil
}
// rendererMarker lets the bridge compiler inspect nil renderer values without
// exposing the private compiled hook type.
type rendererMarker struct{ isNil bool }
View on GitHub (pinned to 7fd6ef3c07)
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.
Example fix
// before
Hooks: common.Hooks{Renderers: map[string]common.Renderer{"pretty": nil}}
// after
Hooks: common.Hooks{Renderers: map[string]common.Renderer{"pretty": func(v any, opts common.RenderOptions) (string, error) { ... }}} Defensive patterns
Strategy: type-guard
Validate before calling
func checkRenderers(r map[string]common.Renderer) error {
for name, fn := range r {
if fn == nil { return fmt.Errorf("renderer %q is nil", name) }
}
return nil
} Type guard
func rendererSet(r map[string]common.Renderer, name string) bool { return r != nil && r[name] != nil } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Hooks.Renderers[%q] is invalid: custom renderers are only su
- Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSO
- Hooks.Execute is required
- %v
- hook %q panic: %v
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/534e3c9db1fb7b48.
Report an issue: GitHub.