hashicorp/terraform · critical

unknown view type %v

Error message

unknown view type %v

What it means

NewStateLocker (internal/command/views/state_locker.go:18) switches over arguments.ViewType and constructs a StateLockerHuman for ViewHuman or StateLockerJSON for ViewJSON; any other rune hits default and panics 'unknown view type %v'. arguments.ViewType is a rune with ViewNone(0), ViewHuman('H'), ViewJSON('J'), ViewRaw('R').

Source

Thrown at internal/command/views/state_locker.go:29

	"github.com/hashicorp/terraform/internal/command/arguments"
)

// The StateLocker view is used to display locking/unlocking status messages
// if the state lock process takes longer than expected.
type StateLocker interface {
	Locking()
	Unlocking()
}

// NewStateLocker returns an initialized StateLocker implementation for the given ViewType.
func NewStateLocker(vt arguments.ViewType, view *View) StateLocker {
	switch vt {
	case arguments.ViewHuman:
		return &StateLockerHuman{view: view}
	case arguments.ViewJSON:
		return &StateLockerJSON{view: view}
	default:
		panic(fmt.Sprintf("unknown view type %v", vt))
	}
}

// StateLockerHuman is an implementation of StateLocker which prints status to
// a terminal.
type StateLockerHuman struct {
	view *View
}

var _ StateLocker = (*StateLockerHuman)(nil)
var _ StateLocker = (*StateLockerJSON)(nil)

func (v *StateLockerHuman) Locking() {
	v.view.streams.Println("Acquiring state lock. This may take a few moments...")
}

func (v *StateLockerHuman) Unlocking() {
	v.view.streams.Println("Releasing state lock. This may take a few moments...")

View on GitHub (pinned to d32a084675)

Solutions

  1. Ensure the command's argument parser always sets ViewType to ViewHuman or ViewJSON before NewStateLocker is reached; default to ViewHuman when no -json flag is present.
  2. If adding a new ViewType, implement the matching StateLocker variant and add its case here in the same change.
  3. Add a unit test that exercises NewStateLocker with every defined ViewType constant to catch missing branches.
  4. If you are a CLI user, this is an internal Terraform bug — report it with the exact subcommand and flags that triggered the panic.

Example fix

// before
default:
    panic(fmt.Sprintf("unknown view type %v", vt))

// after (return a safe default view instead of crashing)
default:
    return &StateLockerHuman{view: view}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the ViewType before constructing a StateLocker.
func validLockerViewType(vt arguments.ViewType) bool {
    return vt == arguments.ViewHuman || vt == arguments.ViewJSON
}
// caller:
if !validLockerViewType(args.ViewType) {
    return nil, fmt.Errorf("state locker requires ViewHuman or ViewJSON, got %v", args.ViewType)
}

Prevention

When it happens

Trigger: A state-modifying command path invokes NewStateLocker with a ViewType that is neither ViewHuman nor ViewJSON — i.e. ViewNone (uninitialized zero value leaking through), ViewRaw, or a rune introduced without updating this switch.

Common situations: A code change that constructs a StateShow/StateMigrate/etc. arguments struct without setting ViewType (leaving ViewNone), a new output mode added to arguments.types.go without a matching StateLocker implementation, or a test/automation harness injecting an unexpected view type.

Related errors


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