qishibo/AnotherRedisDesktopManager · error

Expire Error: ${e.message}

Error message

Expire Error: ${e.message}

What it means

After a successful JSON.SET the component re-applies the header TTL with EXPIRE; this catch fires when that EXPIRE fails. The TTL value itself is rarely the problem — failures are connection-level ('Stream isn't writeable and enableOfflineQueue options is false', closed socket) or ACL denials. A vanished key is not an error here: EXPIRE resolves 0, and this code ignores the reply.

Source

Thrown at src/components/contents/KeyContentReJson.vue:76

            message: this.$t('message.modify_success'),
            duration: 1000,
          });
        } else {
          this.$message.error({
            message: this.$t('message.modify_failed'),
            duration: 1000,
          });
        }
      }).catch((e) => {
        this.$message.error(e.message);
      });
    },
    setTTL() {
      const ttl = parseInt(this.$parent.$parent.$refs.keyHeader.keyTTL);

      if (ttl > 0) {
        this.client.expire(this.redisKey, ttl).catch((e) => {
          this.$message.error(`Expire Error: ${e.message}`);
        }).then((reply) => {});
      }
    },
    initShortcut() {
      this.$shortcut.bind('ctrl+s, ⌘+s', this.hotKeyScope, () => {
        // make input blur to fill the new value
        // this.$refs.saveBtn.$el.focus();
        this.execSave();

        return false;
      });
    },
    dumpCommand() {
      const command = `JSON.SET ${this.$util.bufToQuotation(this.redisKey)} . ${
        this.$util.bufToQuotation(this.content)}`;
      this.$util.copyToClipboard(command);
      this.$message.success({ message: this.$t('message.copy_success'), duration: 800 });
    },

View on GitHub (pinned to c149855106)

Solutions

  1. Guard with client.status === 'ready' before issuing EXPIRE, or reconnect first
  2. Grant the ACL user expire or the @keyspace category
  3. Afterwards confirm with TTL key that the expiry actually applied — the code path ignores a 0 reply

Example fix

// before
this.client.expire(this.redisKey, ttl).catch((e) => {
  this.$message.error(`Expire Error: ${e.message}`);
});

// after
if (this.client.status === 'ready') {
  this.client.expire(this.redisKey, ttl).catch((e) => {
    this.$message.error(`Expire Error: ${e.message}`);
  });
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (this.client.status !== 'ready') {
  return; // do not fire EXPIRE into a dead client
}

Try / catch

client.expire(key, ttl)
  .then((reply) => {
    if (reply === 0) {
      // key vanished between write and expire — not an error, but TTL was not set
      this.$message.warning('Key disappeared before TTL could be set');
    }
  })
  .catch((e) => this.$message.error(`Expire Error: ${e.message}`));

Prevention

When it happens

Trigger: Connection dropping immediately after JSON.SET; the ioredis client already in 'end' status when setTTL runs (tab closed concurrently); ACL user without expire/@keyspace permission.

Common situations: Flaky links to managed Redis; TTL re-application racing a disconnect; least-privilege ACL service accounts that forgot @keyspace.

Related errors


AI-assisted analysis of qishibo/AnotherRedisDesktopManager@c149855106 (2026-08-22). Data as JSON: /api/errors/0388ddbc200f87f2. Report an issue: GitHub.