[BUG] AI token limiter rule fields can be null and crash request processing
- Dominant language
- Java
- Stars
- 8.8k
- Forks
- 3.1k
- Avg merge
- 7d 1h
- Merged PRs (30d)
- 85
Description
### Search before asking
- [x] I had searched in the [issues](https://github.com/apache/shenyu/issues) and found no similar issues.
### Apache ShenYu Component
shenyu-plugin
### What happened
`AiTokenLimiterPluginHandler` parses rule handles directly from JSON and caches them without filling defaults:
```java
final AiTokenLimiterHandle rateLimiterHandle = GsonUtils.getInstance().fromJson(s, AiTokenLimiterHandle.class);
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData), rateLimiterHandle);
```
But the runtime assumes `tokenLimit` and `timeWindowSeconds` are always non-null:
```java
Long tokenLimit = aiTokenLimiterHandle.getTokenLimit();
Long timeWindowSeconds = aiTokenLimiterHandle.getTimeWindowSeconds();
...
return isAllowed(reactiveRedisTemplate, cacheKey, tokenLimit)
```
`isAllowed(...)` unboxes `tokenLimit` during comparison:
```java
if (Long.parseLong(currentTokens.toString()) >= tokenLimit) {
return Mono.just(false);
}
```
and token recording passes `timeWindowSeconds` to `Duration.ofSeconds(...)`:
```java
reactiveRedisTemplate.opsForValue()
.increment(cacheKey, tokens)
.flatMap(currentValue -> reactiveRedisTemplate.expire(cacheKey, Duration.ofSeconds(windowSeconds)))
.subscribe();
```
The admin metadata for these rule fields marks them as not required and does not provide default values:
```sql
INSERT INTO plugin_handle ... 'timeWindowSeconds' ... '{"required":"0","rule":""}'
INSERT INTO plugin_handle ... 'tokenLimit' ... '{"required":"0","rule":""}'
```
So a synced/saved rule handle missing either value can cause runtime failures instead of using the documented/default limiter settings.
### Expected behavior
AI token limiter rule handling should validate required fields or apply defaults consistently for rule handles, not only for the selector default-rule path. Missing `tokenLimit` or `timeWindowSeconds` should not crash request processing.
### How to reproduce
1. Enable the `ai-token-limiter` plugin with Redis config.
2. Create or sync a rule handle that omits `tokenLimit`, for example:
```json
{"aiTokenLimitType":"uri","timeWindowSeconds":60,"keyName":"default"}
```
3. Send a request matching the rule.
4. `isAllowed(...)` compares the current token count with a null `tokenLimit` and the request fails.
A handle that omits `timeWindowSeconds` can also fail when response token usage is recorded through `Duration.ofSeconds(windowSeconds)`.
### Debug logs
_No response_
### Environment
Current `master` branch.
### Are you willing to submit a PR?
- [ ] Yes I am willing to submit a PR!
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with AiTokenLimiterPluginHandler and trace how rule handles reach isAllowed(...) and the token-recording expire call after Gson parsing and caching. Compare this path with the selector default-rule handling, and inspect the plugin_handle metadata for tokenLimit and timeWindowSeconds. Done means a synced or saved handle missing either field no longer crashes request processing and the handling is consistent with the documented defaults or validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, redis, sql
- Domain
- api, backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100