koala73/worldmonitor · error · Error

Redis refresh-attempt restore returned an invalid response

Error message

Redis refresh-attempt restore returned an invalid response

What it means

Thrown by `rawRedisRestoreRefreshAttempt` in api/oauth/_refresh-recovery.ts:293 when the restore EVAL returns something other than the integer 0 or 1. The restore Lua script is a compare-and-set that can only return 0 (attempt key mismatch) or 1 (restored), so any other value means the Redis reply was mangled or mis-encoded, not that the restore logically failed (a logical failure is a clean 0 → `false`).

Source

Thrown at api/oauth/_refresh-recovery.ts:293

    "if ARGV[3] ~= '' then redis.call('SET', KEYS[2], ARGV[3], 'EX', ARGV[4]) end",
    "redis.call('DEL', KEYS[3])",
    'return 1',
  ].join('\n');
  const result = await rawRedisEval(
    script,
    [
      `oauth:refresh:${refreshToken}`,
      refreshFamilyPointerKey(refreshToken),
      refreshFamilyAttemptKey(refreshToken),
    ],
    [
      attemptValue,
      JSON.stringify(refreshData),
      familyId ? serializeRefreshFamilyPointer(familyId) : '',
      REFRESH_TTL_SECONDS,
    ],
  );
  if (result !== 0 && result !== 1) throw new Error('Redis refresh-attempt restore returned an invalid response');
  return result === 1;
}

export async function rawRedisFinalizeRefreshAttempt(
  refreshToken: string,
  attemptValue: string,
): Promise<boolean> {
  const script = [
    "if redis.call('GET', KEYS[2]) ~= ARGV[1] then return 0 end",
    "if redis.call('GET', KEYS[1]) == ARGV[2] then redis.call('DEL', KEYS[1]) end",
    "redis.call('DEL', KEYS[2])",
    'return 1',
  ].join('\n');
  const result = await rawRedisEval(
    script,
    [`oauth:refresh:${refreshToken}`, refreshFamilyAttemptKey(refreshToken)],
    [attemptValue, serializeRefreshAttemptMarker(attemptValue)],
  );

View on GitHub (pinned to a96956387a)

Solutions

  1. Log the raw EVAL response to identify what was returned instead of 0/1
  2. Verify the Upstash REST endpoint is reached directly with no body-transforming proxy
  3. Treat as transient/retryable: the caller (restoreRefreshAttempt flow) already catches this and keeps the retryable OAuth response, so a retry after the infra issue clears is safe
Defensive patterns

Strategy: retry

Type guard

function isInvalidRestoreResponse(e: unknown): boolean {
  return e instanceof Error && e.message === 'Redis refresh-attempt restore returned an invalid response';
}

Try / catch

try {
  await restoreRefreshAttempt(token, attemptValue, data, familyId);
} catch (e) {
  if (isInvalidRestoreResponse(e)) {
    // keep the retryable OAuth response and retry after infra recovery;
    // a committed restore is idempotent-safe (compare-and-set guards replay)
    await retryWithBackoff();
  } else throw e;
}

Prevention

When it happens

Trigger: A restore call after a failed OAuth refresh finalization where the EVAL response payload is not a bare 0/1 — reply re-encoding by a proxy, Upstash REST format change, or corrupted JSON body.

Common situations: Same family as other reply-shape guards: Upstash behavior changes, intermediary proxies, or version skew; rare and infrastructure-flavored rather than caller-induced.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@a96956387a (2026-08-27). Data as JSON: /api/errors/b2a6c4afbd2f81f0. Report an issue: GitHub.