Automattic/mongoose · error · CastError
Cast to $text failed for value "${value}" (type ${valueType}
Error message
Cast to $text failed for value "${value}" (type ${valueType}) at path "${path}" What it means
castTextSearch handles the top-level `$text` filter key (lib/cast.js routes `filter.$text` here) and throws CastError '$text' when the value is null or not an object. $text requires an object form — `{ $search: 'term', $language: 'en', $caseSensitive: false, $diacriticSensitive: false }` — and each present sub-option is then cast to its type. Passing the search string bare ('term') or forgetting the object wrapper triggers this before the query ever reaches MongoDB.
Source
Thrown at lib/schema/operators/text.js:20
const CastError = require('../../error/cast');
const castBoolean = require('../../cast/boolean');
const castString = require('../../cast/string');
/**
* Casts val to an object suitable for `$text`. Throws an error if the object
* can't be casted.
*
* @param {any} val value to cast
* @param {string} [path] path to associate with any errors that occurred
* @return {object} casted object
* @see https://www.mongodb.com/docs/manual/reference/operator/query/text/
* @api private
*/
module.exports = function castTextSearch(val, path) {
if (val == null || typeof val !== 'object') {
throw new CastError('$text', val, path);
}
if (val.$search != null) {
val.$search = castString(val.$search, path + '.$search');
}
if (val.$language != null) {
val.$language = castString(val.$language, path + '.$language');
}
if (val.$caseSensitive != null) {
val.$caseSensitive = castBoolean(val.$caseSensitive,
path + '.$caseSensitive');
}
if (val.$diacriticSensitive != null) {
val.$diacriticSensitive = castBoolean(val.$diacriticSensitive,
path + '.$diacriticSensitive');
}
return val;View on GitHub (pinned to 49cdab0136)
Solutions
- Always use the object form: `Model.find({ $text: { $search: term } })`
- Default-construct the object when the term may be absent: `const q = term ? { $text: { $search: term } } : {}`
- Ensure a text index exists (`schema.index({ body: 'text' })`) — without it a valid $text query fails server-side with a different error
- Validate search input is a non-empty string before composing the filter
Example fix
// before
const results = await Model.find({ $text: req.query.q }); // bare string
// after
const q = String(req.query.q ?? '').trim();
if (!q) return [];
const results = await Model.find({ $text: { $search: q } }); Defensive patterns
Strategy: validation
Validate before calling
function toTextFilter(term) {
const q = String(term ?? '').trim();
if (!q) return {}; // no text search
return { $text: { $search: q } }; // always object form
} Type guard
function isTextFilter(v) {
return v != null && typeof v === 'object' && typeof v.$search === 'string';
} Try / catch
try { await Model.find({ $text: value }); } catch (err) { if (err.name === 'CastError' && err.kind === '$text') { return badRequest('$text requires { $search: string }'); } throw err; } Prevention
- Always wrap the term: { $search: term }
- Skip $text entirely for empty search strings instead of passing ''
- Create the text index before shipping $text endpoints
When it happens
Trigger: `Model.find({ $text: 'hello' })` (bare string), `Model.find({ $text: null })`, or `{ $text: { $search: 123 } }` (inner options then fail their own casts via castString/castBoolean on `path.$search` etc.). Note $text is a top-level filter key, never placed under a field path.
Common situations: Wrapping a search term directly instead of `{ $search: ... }`; query-builder code that short-circuits empty searches to the raw string; missing text index is a *different* (server-side) error — this one is purely shape validation on the filter.
Related errors
- Query filter must be an object, got an array ${util.inspect(
- Cast to Array failed for value "${value}" at path "${path}"
- Cast to Object failed for value "${value}" at path "${path}.
- Cast to number failed for value "${value}" (type ${valueType
- Cast to string failed for value "${value}" (type ${valueType
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/7b010d15677f7ca4.
Report an issue: GitHub.