tailscale/tailscale · error
tailnet lock is not enabled
Error message
tailnet lock is not enabled
What it means
runTailnetLockRemove (cmd/tailscale/cli/tailnet-lock.go:347) checks st.Enabled after fetching TailnetLockStatus; if tailnet lock is not enabled there are no trusted keys to remove, so the command returns this error before attempting any modification.
Source
Thrown at cmd/tailscale/cli/tailnet-lock.go:347
fs.BoolVar(&nlRemoveArgs.resign, "re-sign", true, "resign signatures which would be invalidated by removal of trusted signing keys")
return fs
})(),
}
func runTailnetLockRemove(ctx context.Context, args []string) error {
removeKeys, _, err := parseTLArgs(args, true, false)
if err != nil {
return err
}
if len(removeKeys) == 0 {
return fmt.Errorf("missing argument, expected one or more tailnet lock keys")
}
st, err := localClient.TailnetLockStatus(ctx)
if err != nil {
return fixTailscaledConnectError(err)
}
if !st.Enabled {
return errors.New("tailnet lock is not enabled")
}
if len(st.TrustedKeys) == 1 {
return errors.New("cannot remove the last trusted signing key; use 'tailscale lock disable' to disable tailnet lock instead, or add another signing key before removing one")
}
if nlRemoveArgs.resign {
// Validate we are not removing trust in ourselves while resigning. This is because
// we resign with our own key, so the signatures would be immediately invalid.
for _, k := range removeKeys {
kID, err := k.ID()
if err != nil {
return fmt.Errorf("computing KeyID for key %v: %w", k, err)
}
if bytes.Equal(st.PublicKey.KeyID(), kID) {
return errors.New("cannot remove local trusted signing key while resigning; run command on a different node or with --re-sign=false")
}
}
View on GitHub (pinned to cfe32b8be6)
Solutions
- Verify with `tailscale lock status` that lock is enabled
- If you intended to start using lock, run `tailscale lock init ...` first
- If lock was intentionally disabled, drop the remove step from your runbook
Example fix
# before $ tailscale lock remove tlpub:... # after $ tailscale lock init tlpub:... && tailscale lock remove tlpub:...
Defensive patterns
Strategy: validation
Validate before calling
st, err := localClient.TailnetLockStatus(ctx)
if err != nil {
return err
}
if !st.Enabled {
return errors.New("cannot remove keys: tailnet lock not enabled; run 'tailscale lock init' first")
} Prevention
- Check `tailscale lock status` before remove in scripts
- Order runbooks: init before add/remove
- Detect post-disable state and skip stale key operations
When it happens
Trigger: Running `tailscale lock remove tlpub:...` on a tailnet where lock was never initialized (st.Enabled == false), or after it was disabled.
Common situations: Running remove before init in setup scripts; lock was disabled with a disablement secret and someone retries stale remove commands; wrong tailnet (different account) where lock is off.
Related errors
- tailnet lock is already enabled
- Tailnet Lock is not enabled
- the tailnet lock key of the current node must be one of the
- cannot remove the last trusted signing key; use 'tailscale l
- cannot remove local trusted signing key while resigning; run
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/ef351c63c5148eb9.
Report an issue: GitHub.