Repository navigation
v2.18.1
Patch release that checks Firebird event names before they are sent. registerEvent() and the lower-level op_que_events path now reject empty names and names longer than 127 UTF-8 bytes, which is the limit Firebird sets for POST_EVENT. An invalid name is reported through the callback and the current subscription stays unchanged. Nothing else in the API changes, and valid event names behave exactly as before.
Summary of Changes
Firebird limits event names to 127 bytes (POST_EVENT reference). In op_que_events, the event parameter buffer (EPB) stores each name's length in a single byte. Before this release the driver did not check names at all:
- An empty name (
'') was queued as a zero-length entry that noPOST_EVENTcan ever match. - A name longer than 255 bytes did not fit in the one-byte length prefix.
Buffer.writeUInt8then threw an uncaughtRangeErrorfrom inside the queuing code. The error never reached the callback, and the name had already been added to the subscription. - A name between 128 and 255 bytes was sent even though Firebird can never post an event with that name, so the listener was never called.
registerEvent()added names to the subscription before anything was checked. One bad name in a batch could therefore leave the subscription partly changed.
Version 2.18.1 checks every name up front and fails the whole call without side effects.
Key Changes
1. Event names are checked in registerEvent() (#440)
db.attachEvent(function (err, evtmgr) {
if (err) throw err;
evtmgr.registerEvent(['order_created', ''], function (err) {
// err.message === 'Firebird event names must be between 1 and 127 UTF-8 bytes.'
// 'order_created' was NOT added: the registered event set is unchanged
});
});- All names in the call are checked before
self.eventsis changed. The call either applies completely or not at all. - The limit is measured in UTF-8 bytes, not JavaScript characters. For example,
'é'.repeat(64)is 64 characters but 128 bytes, so it is rejected. - A name of exactly 127 bytes is accepted.
- A value that is not a string (such as
nullor a number) is also rejected with the same error. - The check runs after the existing closed-connection check, so a closed manager still reports the closed-connection error first.
- The behavior is the same with or without
eventBaseline: true(added in 2.18.0). A failed registration never re-queues the subscription or starts a new baseline.
2. Second check where op_que_events is built
Connection.queEvents() checks each encoded name again while it builds the EPB. If a name is invalid, it reports the error through the callback and sends no packet. This covers code that calls the lower-level wire API directly and bypasses FbEventManager.
3. Documentation
The Database Events section of the README now states the 1–127 UTF-8 byte limit, links to the Firebird reference, and describes what happens on an invalid name.
Behavior Matrix
| Event name | UTF-8 bytes | 2.18.0 | 2.18.1 |
|---|---|---|---|
'NEW_ORDER' |
9 | ✅ Registered | ✅ Registered |
'x'.repeat(127) |
127 | ✅ Registered | ✅ Registered |
'' |
0 | ❌ Error, subscription unchanged | |
'x'.repeat(128) |
128 | ❌ Error, subscription unchanged | |
'é'.repeat(64) |
128 | ❌ Error, subscription unchanged | |
'x'.repeat(300) |
300 | 💥 Uncaught RangeError thrown |
❌ Error, subscription unchanged |
Upgrade Notes
- No configuration changes are needed. Apps that only use valid event names will see no difference.
- If your code builds event names at runtime (from table names, tenant IDs, user input and so on), handle the error from the
registerEvent()callback. Those names used to fail silently and now report an error. - If you build names from non-ASCII text, check their byte length with
Buffer.byteLength(name, 'utf8'), notname.length.
evtmgr.registerEvent(names, function (err) {
if (err) {
console.error('Event registration rejected:', err.message);
return;
}
// subscription active
});Testing
New unit tests in test/unit/event-connection.test.ts cover:
- empty names
- ASCII names over the limit (128 bytes)
- multibyte names over the limit (fewer than 127 characters but more than 127 bytes)
- names of exactly 127 bytes, which are accepted
- a failed registration does not partly change the registered set and does not re-queue the subscription, both with and without
eventBaseline
Build, typecheck, lint and the full unit suite (245 tests) pass. The CI matrix passes on Node.js 20, 22, 24 and 26 against Firebird 3, 4, 5 and the 6 snapshot.
Pull Requests
Related
- v2.18.0 added the opt-in
eventBaselinemode (#437) and bounded tracking of retired baseline event IDs (#439). This release completes that round of work on events.
Installation
npm install node-firebird@2.18.1Full Changelog: v2.18.0...v2.18.1
🤖 Generated with Claude Code