larksuite/cli · error

Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSO

Error message

Hooks.Renderers[%q] conflicts with Output.Mode %q: fixed JSON output does not execute custom renderers

What it means

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.

Source

Thrown at shortcuts/common/typed_compile_output.go:27

	"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

  1. Remove the Hooks.Renderers entry when Output.Mode is fixed JSON.
  2. Change Output.Mode back to the default (non-fixed) mode if custom pretty rendering is required.
  3. Keep the renderer but gate registration so it is only provided for commands not in fixed-JSON mode.

Example fix

// before
Output: common.Output{Mode: common.OutputModeFixedJSON},
Hooks: common.Hooks{Renderers: map[string]Renderer{"pretty": prettyFn}}
// after
Output: common.Output{Mode: common.OutputModeFixedJSON},
Hooks: common.Hooks{} // or drop the fixed-JSON mode to keep the renderer
Defensive patterns

Strategy: validation

Validate before calling

func modeRendererConflict(mode common.OutputMode, r map[string]common.Renderer) error {
  if mode == common.OutputModeFixedJSON && len(r) > 0 {
    return fmt.Errorf("custom renderers are ignored in fixed-JSON mode")
  }
  return nil
}

Prevention

When it happens

Trigger: CompileCommandDefinition with Output.Mode set to the fixed-JSON mode and a non-empty Hooks.Renderers map (e.g. {"pretty": fn}).

Common situations: 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.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/a1dd4849e5af5656. Report an issue: GitHub.