{"record":{"id":"ef351c63c5148eb9","repo":"tailscale/tailscale","slug":"tailnet-lock-is-not-enabled","errorCode":null,"errorMessage":"tailnet lock is not enabled","messagePattern":"tailnet lock is not enabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/tailscale/cli/tailnet-lock.go","lineNumber":347,"sourceCode":"\t\tfs.BoolVar(&nlRemoveArgs.resign, \"re-sign\", true, \"resign signatures which would be invalidated by removal of trusted signing keys\")\n\t\treturn fs\n\t})(),\n}\n\nfunc runTailnetLockRemove(ctx context.Context, args []string) error {\n\tremoveKeys, _, err := parseTLArgs(args, true, false)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(removeKeys) == 0 {\n\t\treturn fmt.Errorf(\"missing argument, expected one or more tailnet lock keys\")\n\t}\n\tst, err := localClient.TailnetLockStatus(ctx)\n\tif err != nil {\n\t\treturn fixTailscaledConnectError(err)\n\t}\n\tif !st.Enabled {\n\t\treturn errors.New(\"tailnet lock is not enabled\")\n\t}\n\tif len(st.TrustedKeys) == 1 {\n\t\treturn 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\")\n\t}\n\n\tif nlRemoveArgs.resign {\n\t\t// Validate we are not removing trust in ourselves while resigning. This is because\n\t\t// we resign with our own key, so the signatures would be immediately invalid.\n\t\tfor _, k := range removeKeys {\n\t\t\tkID, err := k.ID()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"computing KeyID for key %v: %w\", k, err)\n\t\t\t}\n\t\t\tif bytes.Equal(st.PublicKey.KeyID(), kID) {\n\t\t\t\treturn errors.New(\"cannot remove local trusted signing key while resigning; run command on a different node or with --re-sign=false\")\n\t\t\t}\n\t\t}\n","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/tailscale/cli/tailnet-lock.go#L329-L365","documentation":"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.","triggerScenarios":"Running `tailscale lock remove tlpub:...` on a tailnet where lock was never initialized (st.Enabled == false), or after it was disabled.","commonSituations":"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.","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"],"exampleFix":"# before\n$ tailscale lock remove tlpub:...\n# after\n$ tailscale lock init tlpub:... && tailscale lock remove tlpub:...","handlingStrategy":"validation","validationCode":"st, err := localClient.TailnetLockStatus(ctx)\nif err != nil {\n    return err\n}\nif !st.Enabled {\n    return errors.New(\"cannot remove keys: tailnet lock not enabled; run 'tailscale lock init' first\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check `tailscale lock status` before remove in scripts","Order runbooks: init before add/remove","Detect post-disable state and skip stale key operations"],"tags":["tailnet-lock","cli","state-conflict"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}