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
- Unwrap DocumentView: pass view.document (a trix Document) instead of the view.
- Parse HTML strings with HTMLParser.parse(html).getDocument().
- Pass HTMLElements directly; they are converted internally.
- 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
- Unwrap DocumentView objects (use .getDocument()) before serializing.
- Convert all string inputs via HTMLParser.parse first.
- Add runtime assertions in custom serialization pipelines.
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
- unserializable object
- unknown content type:
- unknown content type: ${contentType}
- This browser does not support the .form property for trix-ed
- This browser does not support the .name property for trix-ed
AI-assisted analysis of basecamp/trix@4700401311 (2026-09-02).
Data as JSON: /api/errors/3558ee47673f0503.
Report an issue: GitHub.