{"record":{"id":"a1dd4849e5af5656","repo":"larksuite/cli","slug":"hooks-renderers-q-conflicts-with-output-mode-q","errorCode":null,"errorMessage":"Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSON output does not execute custom renderers","messagePattern":"Hooks\\.Renderers\\[%q\\] conflicts with Output\\.Mode %q: fixed JSON output does not execute custom renderers","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_output.go","lineNumber":27,"sourceCode":"\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":9,"sourceCodeEnd":36,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_output.go#L9-L36","documentation":"When Output.Mode is fixed JSON (typedOutputFixedJSON), the command always emits its declared fixed JSON shape and never executes custom renderers. Registering a custom renderer (under \"pretty\") alongside that mode is therefore a contradiction the compiler rejects, since the renderer would silently never run.","triggerScenarios":"CompileCommandDefinition with Output.Mode set to the fixed-JSON mode and a non-empty Hooks.Renderers map (e.g. {\"pretty\": fn}).","commonSituations":"Switching a command to fixed JSON for machine-readable output but leaving a previously added pretty renderer registered; copy-pasting a hooks block from another command that used custom pretty rendering.","solutions":["Remove the Hooks.Renderers entry when Output.Mode is fixed JSON.","Change Output.Mode back to the default (non-fixed) mode if custom pretty rendering is required.","Keep the renderer but gate registration so it is only provided for commands not in fixed-JSON mode."],"exampleFix":"// before\nOutput: common.Output{Mode: common.OutputModeFixedJSON},\nHooks: common.Hooks{Renderers: map[string]Renderer{\"pretty\": prettyFn}}\n// after\nOutput: common.Output{Mode: common.OutputModeFixedJSON},\nHooks: common.Hooks{} // or drop the fixed-JSON mode to keep the renderer","handlingStrategy":"validation","validationCode":"func modeRendererConflict(mode common.OutputMode, r map[string]common.Renderer) error {\n  if mode == common.OutputModeFixedJSON && len(r) > 0 {\n    return fmt.Errorf(\"custom renderers are ignored in fixed-JSON mode\")\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When setting Output.Mode to fixed JSON, clear Hooks.Renderers in the same change.","Decide per command: either custom pretty rendering or fixed-JSON output, not both.","Review Output and Hooks blocks together during code review of typed commands."],"tags":["hooks","output-mode","conflict","compile-time"],"backgroundTag":"config-conflict","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"}