{"record":{"id":"4441952e6135b4db","repo":"larksuite/cli","slug":"hooks-renderers-q-is-invalid-custom-renderers-a","errorCode":null,"errorMessage":"Hooks.Renderers[%q] is invalid: custom renderers are only supported for pretty; table, csv, and ndjson use framework formatters","messagePattern":"Hooks\\.Renderers\\[%q\\] is invalid: custom renderers are only supported for pretty; table, csv, and ndjson use framework formatters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_output.go","lineNumber":24,"sourceCode":"\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":6,"sourceCodeEnd":36,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_output.go#L6-L36","documentation":"Custom renderers may only be registered under the \"pretty\" key. The framework owns the table, csv, and ndjson formatters, so registering a renderer with any other name is rejected at compile time to prevent silently shadowing or bypassing framework output formats that the CLI contract guarantees.","triggerScenarios":"CompileCommandDefinition with Hooks.Renderers keyed by something other than \"pretty\", e.g. map[string]Renderer{\"table\": myTableRenderer} or {\"json\": ...} or {\"csv\": ...}.","commonSituations":"Assuming all output formats are customizable; porting a config where renderers were once keyed by format name; adding a brand-new format name hoping the framework would pick it up.","solutions":["Rename the renderer key to \"pretty\" if a custom human-readable rendering is intended.","Delete the entry and rely on the built-in framework formatter for table/csv/ndjson.","Customize the underlying data (Output.Data shape/overrides) rather than replacing framework formatters."],"exampleFix":"// before\nRenderers: map[string]Renderer{\"table\": renderTable}\n// after\nRenderers: map[string]Renderer{\"pretty\": renderPretty}","handlingStrategy":"validation","validationCode":"func onlyPrettyRenderers(r map[string]common.Renderer) error {\n  for name := range r {\n    if name != \"pretty\" {\n      return fmt.Errorf(\"renderer %q not allowed; only \\\"pretty\\\" is customizable\", name)\n    }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only ever key Hooks.Renderers with \"pretty\".","Treat table/csv/ndjson formats as framework-owned; customize data shape instead.","Grep for Renderers map literals when migrating code between commands."],"tags":["hooks","renderers","output-format","compile-time"],"backgroundTag":"unsupported-renderer-format","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"}