vitest-dev/vitest · error · PrettyFormatPluginError

${error.message}

Error message

${error.message}

What it means

While serializing a value, pretty-format invokes the matching plugin's `serialize` (new-style) or `print` (old-style). If that call throws, the error is wrapped in a `PrettyFormatPluginError` carrying the original message and stack so the culprit plugin is identifiable. The text shown is the original error's `.message`.

Source

Thrown at packages/pretty-format/src/index.ts:355

          val,
          valChild => printer(valChild, config, indentation, depth, refs),
          (str) => {
            const indentationNext = indentation + config.indent
            return (
              indentationNext
              + str.replaceAll(NEWLINE_REGEXP, `\n${indentationNext}`)
            )
          },
          {
            edgeSpacing: config.spacingOuter,
            min: config.min,
            spacing: config.spacingInner,
          },
          config.colors,
        )
  }
  catch (error: any) {
    throw new PrettyFormatPluginError(error.message, error.stack)
  }
  if (typeof printed !== 'string') {
    throw new TypeError(
      `pretty-format: Plugin must return type "string" but instead returned "${typeof printed}".`,
    )
  }
  return printed
}

function findPlugin(plugins: Plugins, val: unknown) {
  for (const plugin of plugins) {
    try {
      if (plugin.test(val)) {
        return plugin
      }
    }
    catch (error: any) {
      throw new PrettyFormatPluginError(error.message, error.stack)

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Read the `PrettyFormatPluginError.stack` to identify which plugin threw.
  2. Make the offending object's getter non-throwing, or avoid snapshotting it directly.
  3. Disable the culprit plugin by passing a filtered `plugins` array to `format()`.
  4. Wrap your own plugin's serialize in try/catch and return a fallback string.

Example fix

// before: custom plugin throws on null
const plugin = {
  test: v => v?.custom,
  serialize: v => v.custom.toString(), // throws if v.custom is null
}

// after
custom:
const plugin = {
  test: v => v?.custom != null,
  serialize: v => String(v.custom),
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  format(value, { plugins: [myCustomPlugin, ...plugins] })
}
catch (err) {
  if (err instanceof Error && err.name === 'PrettyFormatPluginError') {
    console.error('Plugin failed:', err.message, '\n', err.stack)
    // fall back to a minimal safe serialization
    return safeStringify(value)
  }
  throw err
}

Prevention

When it happens

Trigger: A plugin's serialize accesses a property whose getter throws; a built-in plugin (React/DOM/Immutable) chokes on an exotic object; a custom plugin has a runtime bug triggered by the specific value.

Common situations: Snapshotting objects with throwing getters; serializing Proxy objects; third-party pretty-format plugins; React/DOM element plugin hitting non-standard instances.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/1368d1bb49bc8103.json. Report an issue: GitHub.