siyuan-note/siyuan · error
marshal inline styles failed: %w
Error message
marshal inline styles failed: %w
What it means
After merging the incoming styles with the current AV state, the result is serialized with gulu.JSON.MarshalIndentJSON before being written to disk. A marshal failure here means the resulting InlineStyles structure could not be converted to JSON — typically caused by unsupported types or a MarshalJSON implementation error deeper in the structure. The write is aborted and the original file untouched.
Source
Thrown at kernel/model/inline_style.go:279
if 0 < len(changedCustomColorIndexes) {
removedIndexes := removedAttributeViewCustomColorIndexes(currentAV.Colors, ret.AV.Colors)
customColorUsage, err = workspaceAttributeViewCustomColorUsage(0 < len(removedIndexes))
if err != nil {
return nil, false, err
}
for _, avID := range sortedAttributeViewUsageIDs(customColorUsage) {
indexes := customColorUsage[avID]
for index := range removedIndexes {
if _, used := indexes[index]; used {
return nil, false, fmt.Errorf("attribute view custom color [%d] is still in use by attribute view [%s]",
index, avID)
}
}
}
}
data, err := gulu.JSON.MarshalIndentJSON(ret, "", " ")
if err != nil {
return nil, false, fmt.Errorf("marshal inline styles failed: %w", err)
}
if maxInlineStylesFileSize < len(data) {
return nil, false, fmt.Errorf("inline styles file exceeds the %d byte limit", maxInlineStylesFileSize)
}
dataPath := inlineStylesPath()
oldData, readErr := filelock.ReadFile(dataPath)
if readErr != nil && !os.IsNotExist(readErr) {
return nil, false, fmt.Errorf("read inline styles failed: %w", readErr)
}
if bytes.Equal(oldData, data) {
cacheWorkspaceAVPalette(ret.AV)
return ret, false, nil
}
if err = os.MkdirAll(filepath.Dir(dataPath), 0755); err != nil {
return nil, false, fmt.Errorf("create inline styles directory failed: %w", err)
}View on GitHub (pinned to 8641553a1f)
Solutions
- Inspect any custom MarshalJSON on InlineStyles/InlineStyle types and fix the error it returns
- Remove or make JSON-serializable any non-standard fields added to the styles structures
- Log the underlying wrapped error (%w) to identify the exact field that failed
- Retry with a minimal payload (empty Styles) to confirm the failure comes from payload content
Example fix
// before
type InlineStyle struct { Callback func() `json:"cb"` } // json cannot marshal funcs
// after
type InlineStyle struct { Color string `json:"color"` } Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := json.Marshal(ret); err != nil {
return fmt.Errorf("payload not serializable: %w", err)
} Try / catch
_, _, err := model.SetInlineStyles(styles)
if err != nil && strings.HasPrefix(err.Error(), "marshal inline styles failed") {
log.Fatalf("styles payload not serializable: %v", err)
} Prevention
- Keep only JSON-serializable fields in InlineStyles/InlineStyle structures
- Test any custom MarshalJSON implementations against the full styles structure
- Avoid injecting runtime-only values (funcs, channels) into palette data
When it happens
Trigger: A custom type inside InlineStyles/InlineStyleAV (or injected fields) whose MarshalJSON returns an error; corrupted in-memory structures containing channels/funcs that json cannot encode (usually only possible via code modifications or plugin-supplied values).
Common situations: Custom kernel builds adding non-serializable fields to InlineStyles; middleware that stores arbitrary values into the styles map before persisting.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- marshal master password migration failed: %w
- marshal workspace conf [%s] failed: %s
- invalid session data
- decode session data failed: %w
- decode existing session data failed: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/46e3b8a51c3a1955.
Report an issue: GitHub.