OrchardCMS/OrchardCore · error · Error
Message is incomplete.
Error message
Message is incomplete.
What it means
TextMessageFormat.parse throws 'Message is incomplete.' when the input text does not end with the SignalR record separator (0x1E). The text wire protocol frames every message with this separator; a payload missing it cannot be split reliably, so parsing aborts. This protects against truncated or non-protocol data.
Solutions
- Append the record separator before parsing: `data + String.fromCharCode(0x1e)`
- If receiving over WebSocket, buffer chunks until a frame ending with 0x1E arrives instead of parsing partial data
- Verify any custom server/client serialization writes TextMessageFormat.write() output, not raw JSON
Example fix
// before
const messages = TextMessageFormat.parse(jsonString); // throws if no separator
// after
const framed = jsonString.endsWith('\u001e') ? jsonString : jsonString + '\u001e';
const messages = TextMessageFormat.parse(framed); Defensive patterns
Strategy: validation
Validate before calling
if (typeof input !== 'string' || !input.endsWith('\u001e')) throw new Error('Frame must end with record separator 0x1E'); Type guard
const isCompleteFrame = (s) => typeof s === 'string' && s.charCodeAt(s.length - 1) === 0x1e;
Try / catch
try { messages = TextMessageFormat.parse(input); } catch (e) { if (e.message === 'Message is incomplete.') bufferForLater(input); } Prevention
- Always frame with TextMessageFormat.write
- Buffer partial frames instead of parsing immediately
- Avoid pipelines that strip control characters
When it happens
Trigger: Feeding a raw JSON string without the trailing \u001E into TextMessageFormat.parse or message parsers that use it; receiving a partial/truncated frame from the server; sending server data through a custom pipeline that strips the separator.
Common situations: Custom middleware (proxies, loggers) rewriting frames and dropping the 0x1E byte; unit tests hand-writing handshake payloads; parsing captured logs of partial writes on flaky WebSocket connections.
Related errors
- Expected a handshake response from the server.
- Cannot convert to TimeSpan
- Invalid switch syntax
- Unknown command
- The ClamAV antivirus scanner returned an unexpected…
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/97efe79682458fa5.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js:849
return this._httpClient.send(request);
}
getCookieString(url) {
return this._httpClient.getCookieString(url);
}
}
;// CONCATENATED MODULE: ./src/TextMessageFormat.ts
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// Not exported from index
/** @private */
class TextMessageFormat {
static write(output) {
return `${output}${TextMessageFormat.RecordSeparator}`;
}
static parse(input) {
if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) {
throw new Error("Message is incomplete.");
}
const messages = input.split(TextMessageFormat.RecordSeparator);
messages.pop();
return messages;
}
}
TextMessageFormat.RecordSeparatorCode = 0x1e;
TextMessageFormat.RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode);
;// CONCATENATED MODULE: ./src/HandshakeProtocol.ts
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/** @private */
class HandshakeProtocol {
// Handshake request is always JSON
writeHandshakeRequest(handshakeRequest) {View on GitHub (pinned to 4306c0717f)