Automattic/mongoose · error · Error

"${value}" is not a valid UUID string

Error message

"${value}" is not a valid UUID string

What it means

A Schema.Types.UUID path accepts strings matching mongoose's UUID_FORMAT -- the canonical 8-4-4-4-12 hexadecimal form -- and wraps them in BSON's UUID. Any other string shape (wrong grouping, missing hyphens, braces, non-hex characters) throws this Error with the value quoted in the message.

Source

Thrown at lib/cast/uuid.js:19

'use strict';

const UUID = require('mongodb/lib/bson').UUID;

const UUID_FORMAT = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;

module.exports = function castUUID(value) {
  if (value == null) {
    return value;
  }

  if (value instanceof UUID) {
    return value;
  }
  if (typeof value === 'string') {
    if (UUID_FORMAT.test(value)) {
      return new UUID(value);
    } else {
      throw new Error(`"${value}" is not a valid UUID string`);
    }
  }

  // Re: gh-647 and gh-3030, we're ok with casting using `toString()`
  // **unless** its the default Object.toString, because "[object Object]"
  // doesn't really qualify as useful data
  if (value.toString && value.toString !== Object.prototype.toString) {
    if (UUID_FORMAT.test(value.toString())) {
      return new UUID(value.toString());
    }
  }

  throw new Error(`"${value}" cannot be casted to a UUID`);
};

module.exports.UUID_FORMAT = UUID_FORMAT;

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Normalize before assignment: trim, strip braces and 'urn:uuid:' prefixes, re-insert hyphens if you store compact form
  2. Generate IDs with crypto.randomUUID() or new UUID() from bson so the format is guaranteed
  3. Validate with the same pattern up front and reject early

Example fix

// before
doc.uid = '123e4567e89b12d3a456426614174000'; // missing hyphens

// after
doc.uid = '123e4567-e89b-12d3-a456-426614174000';
Defensive patterns

Strategy: validation

Validate before calling

const { UUID_FORMAT } = require('mongoose/lib/cast/uuid');
function isValidUUIDString(v) {
  return typeof v === 'string' && UUID_FORMAT.test(v);
}
if (!isValidUUIDString(req.params.id)) {
  return res.status(400).json({ error: 'invalid uuid' });
}

Type guard

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function isUUID(v) {
  return typeof v === 'string' && UUID_RE.test(v);
}

Try / catch

try {
  await Model.findById(req.params.id);
} catch (err) {
  if (err.message.includes('is not a valid UUID string')) {
    // treat as 404/400: the id cannot exist in canonical form
  }
  throw err;
}

Prevention

When it happens

Trigger: doc.uid = 'not-a-uuid'; '123e4567e89b12d3a456426614174000' (no hyphens); '{123e4567-e89b-12d3-a456-426614174000}' (braces); values pasted with whitespace; user-supplied IDs taken from URLs.

Common situations: Custom ID generators; third-party IDs that are ULIDs, ObjectIds, or base64 strings sent to UUID fields; manual re-formatting that drops hyphens; format drift between producer and consumer.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/312d69883542ef6c. Report an issue: GitHub.