hashicorp/terraform · error · LockError

the state is already locked by another terraform client

Error message

the state is already locked by another terraform client

What it means

In the NestingMap case, Computed cannot be combined with MinItems > 0. In practice the preceding check (error 11) already forces MinItems to 0 for NestingMap, so this branch is effectively unreachable, but it guards against any future relaxation where MinItems could be nonzero while the block is computed.

Solutions

  1. Ensure MinItems is 0 for NestingMap (resolves the upstream error 11 first).
  2. If Computed is required on a map-shaped block, keep MinItems/MaxItems at 0.
  3. Switch to NestingList/NestingSet if both a min count and Computed are genuinely needed (then see error 10).

Example fix

// before
"computed_map": {
  Nesting: configschema.NestingMap,
  MinItems: 1,
  Block: configschema.Block{Computed: true},
},
// after
"computed_map": {
  Nesting: configschema.NestingMap,
  MinItems: 0,
  MaxItems: 0,
  Block: configschema.Block{Computed: true},
},
Defensive patterns

Strategy: validation

Validate before calling

// Defensive: NestingMap should not combine Computed with MinItems > 0.
func validMapComputed(nb *configschema.NestedBlock) bool {
    return nb.Nesting != configschema.NestingMap || !(nb.Computed && nb.MinItems > 0)
}

Type guard

func mapComputedOk(computed bool, min int) bool { return !computed || min == 0 }

Prevention

When it happens

Trigger: Theoretically a NestingMap with Computed: true and MinItems > 0; in current code the NestingMap MinItems!=0 check at line 111 fires first. Guard at internal_validate.go:114 is `blockS.MinItems > 0 && blockS.Computed`.

Common situations: Not independently reachable today; you will first hit 'MinItems and MaxItems must both be 0 in NestingMap mode'. Treat any encounter as a sign that the NestingMap count constraint was bypassed.

Related errors


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

Appendix: source

Thrown at internal/backend/remote-state/kubernetes/client.go:285

			return "", err
		} else {
			return info.ID, nil
		}
	}

	if lease.Spec.HolderIdentity != nil {
		if *lease.Spec.HolderIdentity == info.ID {
			return info.ID, nil
		}

		currentLockInfo, err := c.getLockInfo(lease)
		if err != nil {
			return "", err
		}

		lockErr := &statemgr.LockError{
			Info: currentLockInfo,
			Err:  errors.New("the state is already locked by another terraform client"),
		}
		return "", lockErr
	}

	lease.Spec.HolderIdentity = pointer.StringPtr(info.ID)
	setLockInfo(lease, info.Marshal())
	_, err = c.kubernetesLeaseClient.Update(ctx, lease, metav1.UpdateOptions{})
	if err != nil {
		return "", err
	}

	return info.ID, err
}

func (c *RemoteClient) Unlock(id string) error {
	leaseName, err := c.createLeaseName()
	if err != nil {
		return err

View on GitHub (pinned to d32a084675)