{"record":{"id":"67e96c85de3edca6","repo":"qishibo/AnotherRedisDesktopManager","slug":"expire-error-e-message-67e96c","errorCode":null,"errorMessage":"Expire Error: ${e.message}","messagePattern":"Expire Error: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/components/contents/KeyContentString.vue","lineNumber":77,"sourceCode":"            message: this.$t('message.modify_success'),\n            duration: 1000,\n          });\n        } else {\n          this.$message.error({\n            message: this.$t('message.modify_failed'),\n            duration: 1000,\n          });\n        }\n      }).catch((e) => {\n        this.$message.error(e.message);\n      });\n    },\n    setTTL() {\n      const ttl = parseInt(this.$parent.$parent.$refs.keyHeader.keyTTL);\n\n      if (ttl > 0) {\n        this.client.expire(this.redisKey, ttl).catch((e) => {\n          this.$message.error(`Expire Error: ${e.message}`);\n        }).then((reply) => {});\n      }\n    },\n    initShortcut() {\n      this.$shortcut.bind('ctrl+s, ⌘+s', this.hotKeyScope, () => {\n        // make input blur to fill the new value\n        // this.$refs.saveBtn.$el.focus();\n        this.execSave();\n\n        return false;\n      });\n    },\n    dumpCommand() {\n      const command = `SET ${this.$util.bufToQuotation(this.redisKey)} ${\n        this.$util.bufToQuotation(this.content)}`;\n      this.$util.copyToClipboard(command);\n      this.$message.success({ message: this.$t('message.copy_success'), duration: 800 });\n    },","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/qishibo/AnotherRedisDesktopManager/blob/c149855106628babcdfb7675a8e7ba9434d2492a/src/components/contents/KeyContentString.vue#L59-L95","documentation":"setTTL() reads the TTL field from the key header (parseInt) and, when it is > 0, issues EXPIRE immediately after the SET that saved the content; failures toast 'Expire Error: <message>'. Note that non-numeric input parses to NaN, which silently skips the EXPIRE (ttl > 0 is false) - so this toast means the command actually ran and failed (connection lost, ACL denial, failover), not malformed input.","triggerScenarios":"Connection dropping between the SET and the follow-up EXPIRE; ACL user allowed set but not expire (command-category restrictions); server failover mid-save. EXPIRE on a key deleted in between returns 0, which is not an error and is swallowed by the empty .then.","commonSituations":"Fine-grained ACLs on shared servers, flaky links to remote Redis, save+TTL racing with another client deleting the key.","solutions":["Reconnect and retry the whole save - SET and EXPIRE here are not atomic","If ACL-managed, grant the expire command (or +@write) to the connection user","Verify both steps applied with TTL key after saving"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// sanitize TTL input before issuing EXPIRE (NaN currently skips silently)\nconst parsed = Number.parseInt(String(keyTTL).trim(), 10);\nif (!Number.isInteger(parsed) || parsed <= 0) {\n  return; // no TTL intended, or fix the input field\n}\nawait client.expire(key, parsed);","typeGuard":null,"tryCatchPattern":"// treat SET+EXPIRE as one unit; report which half failed\ntry {\n  await client.set(key, value);\n} catch (e) { showError(`Set Error: ${e.message}`); return; }\n\ntry {\n  await client.expire(key, ttl);\n} catch (e) { showError(`Expire Error: ${e.message}`); }","preventionTips":["ACL users need both set and expire (or +@write) for save-with-TTL to fully succeed","SET and EXPIRE here are two round-trips - a key deleted in between silently keeps no TTL","Verify with TTL key after saving to confirm the expiry actually attached"],"tags":["redis","expire","ttl","acl","ardm"],"backgroundTag":"redis-command-error","analyzedSha":"c149855106628babcdfb7675a8e7ba9434d2492a","analyzedAt":"2026-08-22T09:06:28.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}