Expected: The refill interval should be specified in milliseconds. Currently, it is being passed in days, which prevents the refill logic from triggering correctly. As a result, API key credits are not being replenished properly in the apiKey plugin #1817

Closed
opened 2026-03-13 09:05:25 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @raburuz on GitHub (Sep 1, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Bug Report: API Key Refill Not Triggering

Current vs Expected Behavior

Current behavior:
API key credits are not being refilled even after the refill interval has passed. The remaining requests stay at zero, preventing further API calls.

Expected behavior:
After the specified refillInterval, the remaining requests should reset to refillAmount, allowing the API key to be used again.


Steps to Reproduce

  1. Create an API key with refillInterval and refillAmount (e.g., 2 requests every 5 seconds).
const api = await auth.api.createApiKey({ 
  body: {
    userId: ctx.user.id,
    name: input.name,
    
    // Bucket configuration      
    remaining: 4,
    refillInterval: 5_000, // milliseconds https://www.better-auth.com/docs/plugins/api-key#schema
    refillAmount: 2,
  }
});
  1. Make repeated API requests until the remaining requests reach zero.
  2. Wait for the refill interval to pass.
  3. Observe that the API key does not get refilled as expected.
  4. Check the remaining counter; it remains at zero instead of being reset.

Notes:

  • refillInterval is set in milliseconds.
  • The code calculates elapsed time in days, causing the refill logic to fail.

Logs / Code Snippet

https://github.com/better-auth/better-auth/blob/canary/packages/better-auth/src/plugins/api-key/routes/verify-api-key.ts

const timeSinceLastRequest = (now - lastTime) / (1000 * 60 * 60 * 24); // in days "HERE IS THE ISSUE"
if (timeSinceLastRequest > refillInterval) {
    remaining = refillAmount;
    lastRefillAt = new Date();
}

FIX:

const timeSinceLastRequest = (now - lastTime); // en milisegundos

if (timeSinceLastRequest > refillInterval) {
    remaining = refillAmount;
    lastRefillAt = new Date();  
}

Current vs. Expected behavior

Current behavior:
API key credits are not being refilled even after the refill interval has passed. The remaining requests stay at zero, preventing further API calls.

Expected behavior:
After the specified refillInterval, the remaining requests should reset to refillAmount, allowing the API key to be used again.

What version of Better Auth are you using?

1.3.7

System info

System:
    OS: Windows 11 10.0.26100
    CPU: (12) x64 AMD Ryzen 5 5600G with Radeon Graphics
    Memory: 2.53 GB / 15.43 GB
  Browsers:
    Edge: Chromium (139.0.3405.125)
    Internet Explorer: 11.0.26100.1882

Which area(s) are affected? (Select all that apply)

Backend, Documentation, Package

Auth config (if applicable)


Additional context

No response

Originally created by @raburuz on GitHub (Sep 1, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce # Bug Report: API Key Refill Not Triggering ## Current vs Expected Behavior **Current behavior:** API key credits are not being refilled even after the refill interval has passed. The `remaining` requests stay at zero, preventing further API calls. **Expected behavior:** After the specified `refillInterval`, the `remaining` requests should reset to `refillAmount`, allowing the API key to be used again. --- ## Steps to Reproduce 1. Create an API key with `refillInterval` and `refillAmount` (e.g., 2 requests every 5 seconds). ```ts const api = await auth.api.createApiKey({ body: { userId: ctx.user.id, name: input.name, // Bucket configuration remaining: 4, refillInterval: 5_000, // milliseconds https://www.better-auth.com/docs/plugins/api-key#schema refillAmount: 2, } }); ``` 3. Make repeated API requests until the `remaining` requests reach zero. 4. Wait for the refill interval to pass. 5. Observe that the API key **does not get refilled** as expected. 6. Check the `remaining` counter; it remains at zero instead of being reset. **Notes:** - `refillInterval` is set in **milliseconds**. - The code calculates elapsed time in **days**, causing the refill logic to fail. --- ## Logs / Code Snippet [https://github.com/better-auth/better-auth/blob/canary/packages/better-auth/src/plugins/api-key/routes/verify-api-key.ts](https://github.com/better-auth/better-auth/blob/canary/packages/better-auth/src/plugins/api-key/routes/verify-api-key.ts) ```ts const timeSinceLastRequest = (now - lastTime) / (1000 * 60 * 60 * 24); // in days "HERE IS THE ISSUE" if (timeSinceLastRequest > refillInterval) { remaining = refillAmount; lastRefillAt = new Date(); } ``` FIX: ```ts const timeSinceLastRequest = (now - lastTime); // en milisegundos if (timeSinceLastRequest > refillInterval) { remaining = refillAmount; lastRefillAt = new Date(); } ``` ### Current vs. Expected behavior Current behavior: API key credits are not being refilled even after the refill interval has passed. The remaining requests stay at zero, preventing further API calls. Expected behavior: After the specified refillInterval, the remaining requests should reset to refillAmount, allowing the API key to be used again. ### What version of Better Auth are you using? 1.3.7 ### System info ```bash System: OS: Windows 11 10.0.26100 CPU: (12) x64 AMD Ryzen 5 5600G with Radeon Graphics Memory: 2.53 GB / 15.43 GB Browsers: Edge: Chromium (139.0.3405.125) Internet Explorer: 11.0.26100.1882 ``` ### Which area(s) are affected? (Select all that apply) Backend, Documentation, Package ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
GiteaMirror added the pluginbug labels 2026-03-13 09:05:25 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 1, 2025):

Hi @raburuz! I'm Dosu and I’m helping the better-auth team.

The bug is confirmed: the refill logic in the API key plugin calculates the elapsed time in days, but the refill interval is set in milliseconds, so the refill never triggers as expected. The fix is to change the calculation to use milliseconds for both values:

const timeSinceLastRequest = (now - lastTime); // milliseconds
if (timeSinceLastRequest > refillInterval) {
    remaining = refillAmount;
    lastRefillAt = new Date();
}

This issue is not currently tracked or documented elsewhere, and recent PRs have not fixed this specific bug—they only improved date handling and API key initialization logic, not the time unit mismatch in the refill logic source.

It's a good idea to update documentation and code comments to clarify that refillInterval should always be specified in milliseconds to prevent future confusion.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 1, 2025): <!-- Greeting --> Hi @raburuz! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The bug is confirmed: the refill logic in the API key plugin calculates the elapsed time in days, but the refill interval is set in milliseconds, so the refill never triggers as expected. The fix is to change the calculation to use milliseconds for both values: ```ts const timeSinceLastRequest = (now - lastTime); // milliseconds if (timeSinceLastRequest > refillInterval) { remaining = refillAmount; lastRefillAt = new Date(); } ``` This issue is not currently tracked or documented elsewhere, and recent PRs have not fixed this specific bug—they only improved date handling and API key initialization logic, not the time unit mismatch in the refill logic [source](https://github.com/better-auth/better-auth/blob/cf7f2f118147b6a79a99fcf48898408f038390f5/packages/better-auth/src/plugins/api-key/routes/verify-api-key.ts). It's a good idea to update documentation and code comments to clarify that `refillInterval` should always be specified in milliseconds to prevent future confusion. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/34405a25-09b0-465e-8ee4-7d593626686b?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4336)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1817