RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-search-answer-sources

error-invalid-search-answer-sources

Error message

error-invalid-search-answer-sources

What it means

getSearchAnswerMessagesForUser (apps/meteor/server/api/v1/ai-search.ts) builds the source list for the intelligent-search answer endpoint (POST searchAnswer-style route gated on license + intelligentSearchEnabled + answerGenerationConfigured). It collects message IDs from the request's messages array, skipping entries without an _id, deduplicating them. If not even one usable ID remains it throws Meteor error-invalid-search-answer-sources: the answer request carries no citable sources at all.

Source

Thrown at apps/meteor/server/api/v1/ai-search.ts:190

const getSearchAnswerMessagesForUser = async (userId: string, messages: SearchAnswer['messages']) => {
	const messageIds: string[] = [];
	const messageIdSet = new Set<string>();
	const scoreByMessageId = new Map<string, number | undefined>();
	const clampScore = (score: number | undefined): number | undefined =>
		typeof score === 'number' && Number.isFinite(score) ? Math.min(1, Math.max(0, score)) : undefined;
	for (const { _id, score } of messages) {
		if (!_id) {
			continue;
		}
		if (!messageIdSet.has(_id)) {
			messageIdSet.add(_id);
			messageIds.push(_id);
		}
		scoreByMessageId.set(_id, clampScore(score));
	}
	if (!messageIds.length) {
		throw new Meteor.Error('error-invalid-search-answer-sources');
	}

	const docs = await Messages.findVisibleByIds(messageIds, {
		projection: { _id: 1, rid: 1, msg: 1, ts: 1, u: 1 },
	}).toArray();
	const subscribedRoomIds = await getSubscribedRoomIds(
		userId,
		docs.map((message) => message.rid),
	);
	if (docs.length !== messageIds.length || docs.some((message) => !subscribedRoomIds.has(message.rid))) {
		throw new Meteor.Error('error-invalid-search-answer-sources');
	}

	const normalizedDocs = await normalizeMessagesForUser(docs, userId);
	const docsById = new Map(normalizedDocs.map((message) => [message._id, message]));
	const rooms = await getRoomMap(normalizedDocs.map((message) => message.rid));

	const answerMessages = [];

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Pass at least one entry with a non-empty _id: { "messages": [{ "_id": "aobEdbYhXfu5hkeqG", "score": 0.9 }] }
  2. Take source IDs from the ai-search results endpoint rather than fabricating them
  3. If the search step legitimately found nothing, skip the answer request — there is nothing to cite

Example fix

// before
POST /api/v1/ai-search/answer { "messages": [] } // -> error-invalid-search-answer-sources

// after
POST /api/v1/ai-search/answer { "messages": [{ "_id": "aobEdbYhXfu5hkeqG", "score": 0.9 }] }
Defensive patterns

Strategy: validation

Validate before calling

function assertAnswerSources(messages: Array<{ _id?: string; score?: number }>) {
  const ids = messages.filter((m) => typeof m._id === 'string' && m._id.trim() !== '');
  if (!ids.length) throw new Error('answer request needs >=1 message with a non-empty _id');
  return ids;
}

Type guard

const isSearchAnswerSource = (v: unknown): v is { _id: string; score?: number } =>
  typeof v === 'object' && v !== null && typeof (v as any)._id === 'string' && (v as any)._id.length > 0;

Try / catch

try {
  const { data } = await client.post('/api/v1/ai-search/answer', { messages });
} catch (e: any) {
  if (e?.response?.data?.errorType === 'error-invalid-search-answer-sources' && !messages.some((m) => m._id)) {
    throw new ValidationError('no citable sources — run the search step first');
  }
  throw e;
}

Prevention

When it happens

Trigger: POST to the AI search answer endpoint with messages: [] or with entries that all lack _id (e.g. [{score:0.8}]). The endpoint status checks pass, then this validation fails before any DB access.

Common situations: Client forwarding an empty sources array because the upstream search step returned no hits; schema drift where the field is named id/messageId instead of _id; testing the endpoint with placeholder payloads.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/5154609733d17b4d. Report an issue: GitHub.