basecamp/trix · error

unserializable object

Error message

unserializable object

What it means

In src/trix/core/serialization.js, the "application/json" serializer requires a trix Document or HTMLElement; other types throw "unserializable object". Strings must be parsed into a Document before serialization.

Source

Thrown at src/trix/core/serialization.js:32

  "data-trix-store-key",
  "data-trix-mutable",
  "data-trix-placeholder",
  "tabindex",
]
const serializedAttributesAttribute = "data-trix-serialized-attributes"
const serializedAttributesSelector = `[${serializedAttributesAttribute}]`

const blockCommentPattern = new RegExp("<!--block-->", "g")

const serializers = {
  "application/json": function(serializable) {
    let document
    if (serializable instanceof Document) {
      document = serializable
    } else if (serializable instanceof HTMLElement) {
      document = HTMLParser.parse(serializable.innerHTML).getDocument()
    } else {
      throw new Error("unserializable object")
    }

    return document.toSerializableDocument().toJSONString()
  },

  "text/html": function(serializable) {
    let element
    if (serializable instanceof Document) {
      element = DocumentView.render(serializable)
    } else if (serializable instanceof HTMLElement) {
      element = serializable.cloneNode(true)
    } else {
      throw new Error("unserializable object")
    }

    // Remove unserializable elements
    Array.from(element.querySelectorAll(unserializableElementSelector)).forEach((el) => {
      removeNode(el)

View on GitHub (pinned to 4700401311)

Solutions

  1. Unwrap DocumentView: pass view.document (a trix Document) instead of the view.
  2. Parse HTML strings with HTMLParser.parse(html).getDocument().
  3. Pass HTMLElements directly; they are converted internally.
  4. Assert the input type before serializing in custom pipelines.

Example fix

// before
serializeToContentType(documentView, "application/json")
// after
serializeToContentType(documentView.getDocument(), "application/json")
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(value instanceof Document) && !(value instanceof HTMLElement)) {
  value = HTMLParser.parse(String(value ?? "")).getDocument()
}

Type guard

const isTrixSerializable = (v) => v instanceof Document || v instanceof HTMLElement

Try / catch

try {
  return serializeToContentType(value, "application/json")
} catch (e) {
  if (e.message === "unserializable object") {
    return serializeToContentType(HTMLParser.parse(String(value)).getDocument(), "application/json")
  }
  throw e
}

Prevention

When it happens

Trigger: serializeToContentType(x, "application/json") where x is a string, plain object, array, null, or a trix DocumentView instance rather than its Document.

Common situations: Passing DocumentView (the view wrapper) instead of .document; passing editor JSON strings expecting re-serialization; test fixtures using plain JS objects.

Related errors


AI-assisted analysis of basecamp/trix@4700401311 (2026-09-02). Data as JSON: /api/errors/3558ee47673f0503. Report an issue: GitHub.