hashicorp/terraform · critical

unknown view type

Error message

unknown view type %v

What it means

This panic fires in NewRefresh when arguments.ViewType is neither ViewJSON nor ViewHuman. The refresh switch has no case for ViewNone(0) or ViewRaw('R').

Solutions

  1. Set ViewType explicitly to arguments.ViewHuman or arguments.ViewJSON in any code/test calling NewRefresh.
  2. Add a case for any new ViewType to views/refresh.go:41 (and sibling New* switches).
  3. Cover with refresh_test.go.

Example fix

// before
r := arguments.Refresh{} // ViewType == ViewNone
v := views.NewRefresh(r.ViewType, view)
// after
r := arguments.Refresh{ViewType: arguments.ViewHuman}
v := views.NewRefresh(r.ViewType, view)
Defensive patterns

Strategy: type-guard

Validate before calling

switch vt {
case arguments.ViewHuman, arguments.ViewJSON:
  // ok
default:
  return fmt.Errorf("unsupported refresh view type: %v", vt)
}

Type guard

func isValidRefreshViewType(vt arguments.ViewType) bool {
  return vt == arguments.ViewHuman || vt == arguments.ViewJSON
}

Prevention

When it happens

Trigger: `terraform refresh` (now apply -refresh-only) invoked with a ViewType the refresh constructor does not recognize: zero-value ViewType from test code skipping flag parsing, ViewRaw, or a future enum value.

Common situations: A test builds a Refresh view with the default zero ViewType. A maintainer adds a ViewType and forgets to extend NewRefresh. End users cannot trigger via flags.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/407738085b0febda. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/views/refresh.go:41

	Diagnostics(diags tfdiags.Diagnostics)
	HelpPrompt()
}

// NewRefresh returns an initialized Refresh implementation for the given ViewType.
func NewRefresh(vt arguments.ViewType, view *View) Refresh {
	switch vt {
	case arguments.ViewJSON:
		return &RefreshJSON{
			view: NewJSONView(view),
		}
	case arguments.ViewHuman:
		return &RefreshHuman{
			view:         view,
			inAutomation: view.RunningInAutomation(),
			countHook:    &countHook{},
		}
	default:
		panic(fmt.Sprintf("unknown view type %v", vt))
	}
}

// The RefreshHuman implementation renders human-readable text logs, suitable for
// a scrolling terminal.
type RefreshHuman struct {
	view *View

	inAutomation bool

	countHook *countHook
}

var _ Refresh = (*RefreshHuman)(nil)

func (v *RefreshHuman) Outputs(outputValues map[string]*states.OutputValue) {
	if len(outputValues) > 0 {
		v.view.streams.Print(v.view.colorize.Color("[reset][bold][green]\nOutputs:\n\n"))

View on GitHub (pinned to d32a084675)