{"record":{"id":"085093510cb8c9b1","repo":"qishibo/AnotherRedisDesktopManager","slug":"expire-error-e-message","errorCode":null,"errorMessage":"Expire Error: ${e.message}","messagePattern":"Expire Error: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/components/KeyHeader.vue","lineNumber":222,"sourceCode":"      } else {\n        this.setTTL();\n      }\n    },\n    setTTL(keyDeleted = false) {\n      this.client.expire(this.redisKey, this.keyTTL).then((reply) => {\n        if (reply == 1) {\n          this.$message.success({\n            message: this.$t('message.modify_success'),\n            duration: 1000,\n          });\n\n          if (keyDeleted) {\n            this.refreshKeyList(this.redisKey);\n            this.$bus.$emit('removePreTab');\n          }\n        }\n      }).catch((e) => {\n        this.$message.error(`Expire Error: ${e.message}`);\n      });\n    },\n    persistKey() {\n      this.client.persist(this.redisKey).then(() => {\n        this.initShow();\n        this.$message.success(this.$t('message.modify_success'));\n      }).catch((e) => {\n        this.$message.error(`Persist Error: ${e.message}`);\n      });\n    },\n    refreshKeyList(key, type = 'del') {\n      this.$bus.$emit('refreshKeyList', this.client, key, type);\n    },\n    initShortcut() {\n      // refresh\n      this.$shortcut.bind('ctrl+r, ⌘+r, f5', this.hotKeyScope, () => {\n        // make input blur first\n        this.$refs.deleteBtn.$el.focus();","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/qishibo/AnotherRedisDesktopManager/blob/c149855106628babcdfb7675a8e7ba9434d2492a/src/components/KeyHeader.vue#L204-L240","documentation":"KeyHeader.vue TTL flow: when the edited TTL is applied, client.expire/persist (EXPIRE, PERSIST are both in the app's writeCMD table) rejecting shows 'Expire Error: <e.message>'. On a readonly connection the client-side guard rejects before the server is contacted; otherwise the cause is ACL NOPERM or a dropped connection. Note EXPIRE returns 0 (not an error) when the key is missing, so 'no such key' is not the issue here.","triggerScenarios":"Setting a TTL or clicking persist on a readonly-configured connection; ACL user without +expire/@write; auto-refresh firing EXPIRE after the connection dropped.","commonSituations":"Trying to make a key persistent or set expiry on production with readonly enabled; restricted ACL accounts; network changes while the key tab is open.","solutions":["If the readonly-mode message appears, disable Readonly in the connection config and reconnect.","If 'NOPERM', grant +expire +persist (or +@write) to the ACL user.","If connection-related, reconnect and re-apply the TTL."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { writeCMD } from '@/commands.js';\n// EXPIRE/PERSIST are writeCMD entries - readonly blocks them client-side\nconst ttlBlocked = client.options.connectionReadOnly && (writeCMD['EXPIRE'] || writeCMD['PERSIST']);","typeGuard":"const isWriteDenied = (e) => /readonly mode|NOPERM|not allowed/i.test(e.message);","tryCatchPattern":"this.client.expire(this.redisKey, seconds).catch((e) => {\n  if (isWriteDenied(e)) {\n    this.$message.error('TTL change not permitted (readonly connection or ACL)');\n  } else {\n    this.$message.error(`Expire Error: ${e.message}`);\n  }\n});","preventionTips":["Disable TTL-editing UI on readonly connections - EXPIRE and PERSIST are both in writeCMD.","Remember EXPIRE on a missing key returns 0 without error; an error here means permission or connection, not a missing key."],"tags":["expire","persist","ttl","readonly","acl"],"backgroundTag":"redis-write-command-denied","analyzedSha":"c149855106628babcdfb7675a8e7ba9434d2492a","analyzedAt":"2026-08-22T09:06:28.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}