Skip to content

Commit 6d37259

Browse files
TomasPalssonclaude
andcommitted
šŸ›”ļø fix: Strip null content parts on message load to prevent formatAgentMessages crash
The streaming content aggregator builds message content by index and yields a sparse array; an interrupted/partial save persists a hole that serializes to null in MongoDB. On replay, @librechat/agents formatAgentMessages reads part.type with no null guard and crashes. Sanitize content holes at getMessages, the single DB read chokepoint for conversation history, so both already-corrupted and future rows are neutralized for every consumer (formatAgentMessages, token counting, edit path). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 566e20b commit 6d37259

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

ā€Žpackages/data-schemas/src/methods/message.tsā€Ž

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,19 @@ export function createMessageMethods(mongoose: typeof import('mongoose')): Messa
325325
async function getMessages(filter: FilterQuery<IMessage>, select?: string) {
326326
try {
327327
const Message = mongoose.models.Message as Model<IMessage>;
328-
if (select) {
329-
return await Message.find(filter).select(select).sort({ createdAt: 1 }).lean<IMessage[]>();
328+
const query = Message.find(filter).sort({ createdAt: 1 });
329+
const messages = await (select ? query.select(select) : query).lean<IMessage[]>();
330+
/** Drop null/undefined holes from array `content`. The streaming content
331+
* aggregator builds parts by index and yields a sparse array; an interrupted
332+
* run can persist a hole that serializes to `null`. Downstream formatters
333+
* (e.g. formatAgentMessages) read `part.type` and crash on it, so cleaning on
334+
* read neutralizes both already-corrupted rows and any future ones. */
335+
for (const message of messages) {
336+
if (Array.isArray(message.content)) {
337+
message.content = message.content.filter((part) => part != null);
338+
}
330339
}
331-
332-
return await Message.find(filter).sort({ createdAt: 1 }).lean<IMessage[]>();
340+
return messages;
333341
} catch (err) {
334342
logger.error('Error getting messages:', err);
335343
throw err;

0 commit comments

Comments
Ā (0)