{"record":{"id":"97efe79682458fa5","repo":"OrchardCMS/OrchardCore","slug":"message-is-incomplete","errorCode":null,"errorMessage":"Message is incomplete.","messagePattern":"Message is incomplete\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js","lineNumber":849,"sourceCode":"        return this._httpClient.send(request);\n    }\n    getCookieString(url) {\n        return this._httpClient.getCookieString(url);\n    }\n}\n\n;// CONCATENATED MODULE: ./src/TextMessageFormat.ts\n// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n// Not exported from index\n/** @private */\nclass TextMessageFormat {\n    static write(output) {\n        return `${output}${TextMessageFormat.RecordSeparator}`;\n    }\n    static parse(input) {\n        if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) {\n            throw new Error(\"Message is incomplete.\");\n        }\n        const messages = input.split(TextMessageFormat.RecordSeparator);\n        messages.pop();\n        return messages;\n    }\n}\nTextMessageFormat.RecordSeparatorCode = 0x1e;\nTextMessageFormat.RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode);\n\n;// CONCATENATED MODULE: ./src/HandshakeProtocol.ts\n// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\n\n/** @private */\nclass HandshakeProtocol {\n    // Handshake request is always JSON\n    writeHandshakeRequest(handshakeRequest) {","sourceCodeStart":831,"sourceCodeEnd":867,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js#L831-L867","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst messages = TextMessageFormat.parse(jsonString); // throws if no separator\n// after\nconst framed = jsonString.endsWith('\\u001e') ? jsonString : jsonString + '\\u001e';\nconst messages = TextMessageFormat.parse(framed);","handlingStrategy":"validation","validationCode":"if (typeof input !== 'string' || !input.endsWith('\\u001e')) throw new Error('Frame must end with record separator 0x1E');","typeGuard":"const isCompleteFrame = (s) => typeof s === 'string' && s.charCodeAt(s.length - 1) === 0x1e;","tryCatchPattern":"try { messages = TextMessageFormat.parse(input); } catch (e) { if (e.message === 'Message is incomplete.') bufferForLater(input); }","preventionTips":["Always frame with TextMessageFormat.write","Buffer partial frames instead of parsing immediately","Avoid pipelines that strip control characters"],"tags":["protocol","signalr","parsing","websocket"],"backgroundTag":"unexpected-response-shape","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}