@lodestar/reqresp 1.41.0-dev.9fa839a030 → 1.41.0-dev.a35cbde8b3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"responseEncode.d.ts","sourceRoot":"","sources":["../../src/encoders/responseEncode.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,sBAAsB,EAAC,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAwC,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAC,MAAM,aAAa,CAAC;AAK7G;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE;IAAC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAAC,GAC3C,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,CAqBpE;AAED;;;;;;;;;GASG;AACH,wBAAuB,mBAAmB,CACxC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,EACzC,MAAM,EAAE,sBAAsB,EAC9B,YAAY,EAAE,MAAM,GACnB,cAAc,CAAC,MAAM,CAAC,CAQxB"}
1
+ {"version":3,"file":"responseEncode.d.ts","sourceRoot":"","sources":["../../src/encoders/responseEncode.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,sBAAsB,EAAC,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAwC,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAC,MAAM,aAAa,CAAC;AAK7G;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE;IAAC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAAC,GAC3C,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,CAqBpE;AAED;;;;;;;;;GASG;AACH,wBAAuB,mBAAmB,CACxC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,EACzC,MAAM,EAAE,sBAAsB,EAC9B,YAAY,EAAE,MAAM,GACnB,cAAc,CAAC,MAAM,CAAC,CAWxB"}
@@ -1,7 +1,7 @@
1
1
  import { writeEncodedPayload } from "../encodingStrategies/index.js";
2
2
  import { RespStatus } from "../interface.js";
3
3
  import { ContextBytesType } from "../types.js";
4
- import { encodeErrorMessage } from "../utils/index.js";
4
+ import { encodeErrorMessageToBuffer } from "../utils/index.js";
5
5
  const SUCCESS_BUFFER = Buffer.from([RespStatus.SUCCESS]);
6
6
  /**
7
7
  * Yields byte chunks for a `<response>` with a zero response code `<result>`
@@ -41,12 +41,15 @@ export function responseEncodeSuccess(protocol, cbs) {
41
41
  * fn yields exactly one `<error_response>` and afterwards the stream must be terminated
42
42
  */
43
43
  export async function* responseEncodeError(protocol, status, errorMessage) {
44
- // <result>
45
- yield Buffer.from([status]);
46
- // <error_message>? is optional
47
- if (errorMessage) {
48
- yield* encodeErrorMessage(errorMessage, protocol.encoding);
44
+ if (!errorMessage) {
45
+ yield Buffer.from([status]);
46
+ return;
49
47
  }
48
+ // Combine <result> and <error_message> into a single chunk for atomic delivery.
49
+ // Yielding them separately causes a race condition where the stream closes after the
50
+ // status byte but before the error message arrives on the reader side.
51
+ const errorMessageBuffer = await encodeErrorMessageToBuffer(errorMessage, protocol.encoding);
52
+ yield Buffer.concat([Buffer.from([status]), errorMessageBuffer]);
50
53
  }
51
54
  /**
52
55
  * Yields byte chunks for a `<context-bytes>`. See `ContextBytesType` for possible types.
@@ -1 +1 @@
1
- {"version":3,"file":"responseEncode.js","sourceRoot":"","sources":["../../src/encoders/responseEncode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAC,UAAU,EAAyB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAsB,gBAAgB,EAA4C,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAC,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAErD,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkB,EAClB,GAA4C;IAE5C,OAAO,KAAK,SAAS,CAAC,CAAC,8BAA8B,CAAC,MAAM;QAC1D,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,6CAA6C;YAC7C,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;YAE1B,WAAW;YACX,MAAM,cAAc,CAAC;YAErB,gCAAgC;YAChC,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YACnE,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAsB,CAAC;YAC/B,CAAC;YAED,kDAAkD;YAClD,KAAK,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,mBAAmB,CACxC,QAAyC,EACzC,MAA8B,EAC9B,YAAoB;IAEpB,WAAW;IACX,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAE5B,+BAA+B;IAC/B,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,CAAC,CAAC,kBAAkB,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,YAAiC,EAAE,KAAuB;IACjF,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1B,gBAAgB;QAChB,KAAK,gBAAgB,CAAC,KAAK;YACzB,OAAO,IAAI,CAAC;QAEd,4DAA4D;QAC5D,KAAK,gBAAgB,CAAC,UAAU;YAC9B,OAAO,YAAY,CAAC,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"responseEncode.js","sourceRoot":"","sources":["../../src/encoders/responseEncode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAC,UAAU,EAAyB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAsB,gBAAgB,EAA4C,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAC,0BAA0B,EAAC,MAAM,mBAAmB,CAAC;AAE7D,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkB,EAClB,GAA4C;IAE5C,OAAO,KAAK,SAAS,CAAC,CAAC,8BAA8B,CAAC,MAAM;QAC1D,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,6CAA6C;YAC7C,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;YAE1B,WAAW;YACX,MAAM,cAAc,CAAC;YAErB,gCAAgC;YAChC,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YACnE,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAsB,CAAC;YAC/B,CAAC;YAED,kDAAkD;YAClD,KAAK,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,mBAAmB,CACxC,QAAyC,EACzC,MAA8B,EAC9B,YAAoB;IAEpB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,gFAAgF;IAChF,qFAAqF;IACrF,uEAAuE;IACvE,MAAM,kBAAkB,GAAG,MAAM,0BAA0B,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7F,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,YAAiC,EAAE,KAAuB;IACjF,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;QAC1B,gBAAgB;QAChB,KAAK,gBAAgB,CAAC,KAAK;YACzB,OAAO,IAAI,CAAC;QAEd,4DAA4D;QAC5D,KAAK,gBAAgB,CAAC,UAAU;YAC9B,OAAO,YAAY,CAAC,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
@@ -3,6 +3,11 @@ import { Encoding } from "../types.js";
3
3
  * Encodes a UTF-8 string to 256 bytes max
4
4
  */
5
5
  export declare function encodeErrorMessage(errorMessage: string, encoding: Encoding): AsyncGenerator<Buffer>;
6
+ /**
7
+ * Encodes a UTF-8 error message string into a single buffer (max 256 bytes before encoding).
8
+ * Unlike `encodeErrorMessage`, this collects all encoded chunks into one buffer.
9
+ */
10
+ export declare function encodeErrorMessageToBuffer(errorMessage: string, encoding: Encoding): Promise<Buffer>;
6
11
  /**
7
12
  * Decodes error message from network bytes and removes non printable, non ascii characters.
8
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"errorMessage.d.ts","sourceRoot":"","sources":["../../src/utils/errorMessage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAcrC;;GAEG;AACH,wBAAuB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAQ1G;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,mBAAmB,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzF"}
1
+ {"version":3,"file":"errorMessage.d.ts","sourceRoot":"","sources":["../../src/utils/errorMessage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAcrC;;GAEG;AACH,wBAAuB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAQ1G;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1G;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,mBAAmB,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzF"}
@@ -24,6 +24,17 @@ export async function* encodeErrorMessage(errorMessage, encoding) {
24
24
  yield* writeSszSnappyPayload(bytes);
25
25
  }
26
26
  }
27
+ /**
28
+ * Encodes a UTF-8 error message string into a single buffer (max 256 bytes before encoding).
29
+ * Unlike `encodeErrorMessage`, this collects all encoded chunks into one buffer.
30
+ */
31
+ export async function encodeErrorMessageToBuffer(errorMessage, encoding) {
32
+ const chunks = [];
33
+ for await (const chunk of encodeErrorMessage(errorMessage, encoding)) {
34
+ chunks.push(chunk);
35
+ }
36
+ return Buffer.concat(chunks);
37
+ }
27
38
  /**
28
39
  * Decodes error message from network bytes and removes non printable, non ascii characters.
29
40
  */
@@ -1 +1 @@
1
- {"version":3,"file":"errorMessage.js","sourceRoot":"","sources":["../../src/utils/errorMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,IAAI,YAAY,EAAE,cAAc,IAAI,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAC,qBAAqB,EAAC,MAAM,2CAA2C,CAAC;AAChF,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAC;AAExD,uBAAuB;AACvB,EAAE;AACF,IAAI;AACJ,mCAAmC;AACnC,IAAI;AACJ,EAAE;AACF,uFAAuF;AACvF,wFAAwF;AACxF,EAAE;AACF,sHAAsH;AAEtH;;GAEG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,kBAAkB,CAAC,YAAoB,EAAE,QAAkB;IAChF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEzD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,UAAU;YACtB,KAAK,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,mBAA+B;IACtE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,aAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,aAAa,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5G,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,0CAA0C;QAC1C,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,EAAE,EAAE,CAAC;QACZ,0CAA0C;QAC1C,OAAO,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"errorMessage.js","sourceRoot":"","sources":["../../src/utils/errorMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,IAAI,YAAY,EAAE,cAAc,IAAI,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAC,qBAAqB,EAAC,MAAM,2CAA2C,CAAC;AAChF,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAC;AAExD,uBAAuB;AACvB,EAAE;AACF,IAAI;AACJ,mCAAmC;AACnC,IAAI;AACJ,EAAE;AACF,uFAAuF;AACvF,wFAAwF;AACxF,EAAE;AACF,sHAAsH;AAEtH;;GAEG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,kBAAkB,CAAC,YAAoB,EAAE,QAAkB;IAChF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEzD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,UAAU;YACtB,KAAK,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,YAAoB,EAAE,QAAkB;IACvF,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,kBAAkB,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC;QACrE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,mBAA+B;IACtE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,aAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,aAAa,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5G,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,0CAA0C;QAC1C,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,EAAE,EAAE,CAAC;QACZ,0CAA0C;QAC1C,OAAO,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ChainSafe/lodestar/issues"
13
13
  },
14
- "version": "1.41.0-dev.9fa839a030",
14
+ "version": "1.41.0-dev.a35cbde8b3",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
@@ -46,9 +46,9 @@
46
46
  "dependencies": {
47
47
  "@chainsafe/fast-crc32c": "^4.2.0",
48
48
  "@libp2p/interface": "^2.7.0",
49
- "@lodestar/config": "^1.41.0-dev.9fa839a030",
50
- "@lodestar/params": "^1.41.0-dev.9fa839a030",
51
- "@lodestar/utils": "^1.41.0-dev.9fa839a030",
49
+ "@lodestar/config": "^1.41.0-dev.a35cbde8b3",
50
+ "@lodestar/params": "^1.41.0-dev.a35cbde8b3",
51
+ "@lodestar/utils": "^1.41.0-dev.a35cbde8b3",
52
52
  "it-all": "^3.0.4",
53
53
  "it-pipe": "^3.0.1",
54
54
  "snappy": "^7.2.2",
@@ -61,8 +61,8 @@
61
61
  "@libp2p/crypto": "^5.1.7",
62
62
  "@libp2p/logger": "^5.1.21",
63
63
  "@libp2p/peer-id": "^5.1.8",
64
- "@lodestar/logger": "^1.41.0-dev.9fa839a030",
65
- "@lodestar/types": "^1.41.0-dev.9fa839a030",
64
+ "@lodestar/logger": "^1.41.0-dev.a35cbde8b3",
65
+ "@lodestar/types": "^1.41.0-dev.a35cbde8b3",
66
66
  "it-stream-types": "^2.0.2",
67
67
  "libp2p": "2.9.0"
68
68
  },
@@ -77,5 +77,5 @@
77
77
  "reqresp",
78
78
  "blockchain"
79
79
  ],
80
- "gitHead": "1ba8fa66f8fc0890153a0ecc8cd5b3be617ce410"
80
+ "gitHead": "090cdf258f4c067ebe6b5f0bdba221c2c23b9962"
81
81
  }
@@ -1,7 +1,7 @@
1
1
  import {writeEncodedPayload} from "../encodingStrategies/index.js";
2
2
  import {RespStatus, RpcResponseStatusError} from "../interface.js";
3
3
  import {ContextBytesFactory, ContextBytesType, MixedProtocol, Protocol, ResponseOutgoing} from "../types.js";
4
- import {encodeErrorMessage} from "../utils/index.js";
4
+ import {encodeErrorMessageToBuffer} from "../utils/index.js";
5
5
 
6
6
  const SUCCESS_BUFFER = Buffer.from([RespStatus.SUCCESS]);
7
7
 
@@ -55,13 +55,16 @@ export async function* responseEncodeError(
55
55
  status: RpcResponseStatusError,
56
56
  errorMessage: string
57
57
  ): AsyncGenerator<Buffer> {
58
- // <result>
59
- yield Buffer.from([status]);
60
-
61
- // <error_message>? is optional
62
- if (errorMessage) {
63
- yield* encodeErrorMessage(errorMessage, protocol.encoding);
58
+ if (!errorMessage) {
59
+ yield Buffer.from([status]);
60
+ return;
64
61
  }
62
+
63
+ // Combine <result> and <error_message> into a single chunk for atomic delivery.
64
+ // Yielding them separately causes a race condition where the stream closes after the
65
+ // status byte but before the error message arrives on the reader side.
66
+ const errorMessageBuffer = await encodeErrorMessageToBuffer(errorMessage, protocol.encoding);
67
+ yield Buffer.concat([Buffer.from([status]), errorMessageBuffer]);
65
68
  }
66
69
 
67
70
  /**
@@ -28,6 +28,18 @@ export async function* encodeErrorMessage(errorMessage: string, encoding: Encodi
28
28
  }
29
29
  }
30
30
 
31
+ /**
32
+ * Encodes a UTF-8 error message string into a single buffer (max 256 bytes before encoding).
33
+ * Unlike `encodeErrorMessage`, this collects all encoded chunks into one buffer.
34
+ */
35
+ export async function encodeErrorMessageToBuffer(errorMessage: string, encoding: Encoding): Promise<Buffer> {
36
+ const chunks: Buffer[] = [];
37
+ for await (const chunk of encodeErrorMessage(errorMessage, encoding)) {
38
+ chunks.push(chunk);
39
+ }
40
+ return Buffer.concat(chunks);
41
+ }
42
+
31
43
  /**
32
44
  * Decodes error message from network bytes and removes non printable, non ascii characters.
33
45
  */