Based on my current understanding the root cause is a bug in the underlying LRU implementation toad-cache - I will create a dedicated issue there and link it here (update: done).
{"level":30,"time":1701280599225,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-1","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.1"},"msg":"incoming request"}
{"level":30,"time":1701280599227,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-1","res":{"statusCode":200},"responseTime":1.9484590291976929,"msg":"request completed"}
{"level":30,"time":1701280599227,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-2","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.1"},"msg":"incoming request"}
{"level":30,"time":1701280599227,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-2","res":{"statusCode":200},"responseTime":0.15683400630950928,"msg":"request completed"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-3","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.2"},"msg":"incoming request"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-3","res":{"statusCode":200},"responseTime":0.140083909034729,"msg":"request completed"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-4","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.3"},"msg":"incoming request"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-4","res":{"statusCode":200},"responseTime":0.09191691875457764,"msg":"request completed"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-5","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.4"},"msg":"incoming request"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-5","res":{"statusCode":200},"responseTime":0.12541699409484863,"msg":"request completed"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-6","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.5"},"msg":"incoming request"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-6","res":{"statusCode":200},"responseTime":0.0599590539932251,"msg":"request completed"}
{"level":30,"time":1701280599228,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-7","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.6"},"msg":"incoming request"}
{"level":50,"time":1701280599229,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-7","req":{"method":"GET","url":"/","hostname":"localhost:80","remoteAddress":"10.0.0.6"},"res":{"statusCode":500},"err":{"type":"TypeError","message":"Cannot read properties of null (reading 'key')","stack":"TypeError: Cannot read properties of null (reading 'key')\n at LruObject.evict (/workspace/node_modules/toad-cache/dist/toad-cache.cjs:406:30)\n at LruObject.set (/workspace/node_modules/toad-cache/dist/toad-cache.cjs:470:12)\n at LocalStore.incr (/workspace/node_modules/@fastify/rate-limit/store/LocalStore.js:41:12)\n at res (/workspace/node_modules/@fastify/rate-limit/index.js:214:15)\n at new Promise (<anonymous>)\n at Object.<anonymous> (/workspace/node_modules/@fastify/rate-limit/index.js:213:25)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"},"msg":"Cannot read properties of null (reading 'key')"}
{"level":30,"time":1701280599229,"pid":65968,"hostname":"334e6cd6cd00","reqId":"req-7","res":{"statusCode":500},"responseTime":0.6233330965042114,"msg":"request completed"
[17:42:51.262] ERROR (63715): Cannot read properties of null (reading 'key')
reqId: "req-7"
req: {
"method": "GET",
"url": "/",
"hostname": "localhost:80",
"remoteAddress": "10.0.0.6"
}
res: {
"statusCode": 500
}
err: {
"type": "TypeError",
"message": "Cannot read properties of null (reading 'key')",
"stack":
TypeError: Cannot read properties of null (reading 'key')
at LruObject.evict (/workspace/node_modules/toad-cache/dist/toad-cache.cjs:406:30)
at LruObject.set (/workspace/node_modules/toad-cache/dist/toad-cache.cjs:470:12)
at LocalStore.incr (/workspace/node_modules/@fastify/rate-limit/store/LocalStore.js:41:12)
at res (/workspace/node_modules/@fastify/rate-limit/index.js:214:15)
at new Promise (<anonymous>)
at Object.<anonymous> (/workspace/node_modules/@fastify/rate-limit/index.js:213:25)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
}
Prerequisites
Fastify version
4.24.3
Plugin version
9.0.0
Node.js version
20.9.0
Operating system
Linux
Operating system version (i.e. 20.04, 11.3, 10)
Ubuntu 22.04
Description
Hey folks,
first of all thanks for building and maintaining this library ❤️
I found a bug in the most recent version of
fastify-rate-limit(9.0.0at the time of writing) when using the defaultLocalStore.Summary
Based on my current understanding the root cause is a bug in the underlying LRU implementation toad-cache - I will create a dedicated issue there and link it here (update: done).
Impact
If triggered, all routes protected by
fastify-rate-limitwill be persitently error outSteps to Reproduce
create the following file as
repro.mjsand then runnode repro.mjsraw output from
node repro.mjs:prettified stacktrace:
Expected Behavior
Expected Behavior:
Actual Behavior: