siyuan-note/siyuan · error
marshal master password migration failed: %w
Error message
marshal master password migration failed: %w
What it means
gulu.JSON.MarshalIndentJSON failed while serializing the masterPasswordMigration struct for disk persistence. The migration record could not be converted to JSON, so nothing is written and the error is wrapped and returned.
Source
Thrown at kernel/model/crypto.go:544
func masterPasswordMigrationPath() string {
return filepath.Join(util.DataDir, ".siyuan", "master-password-migration.json")
}
func writeMasterPasswordMigration(m *masterPasswordMigration) error {
masterPasswordMigrationMu.Lock()
defer masterPasswordMigrationMu.Unlock()
return writeMasterPasswordMigrationUnlocked(m)
}
func writeMasterPasswordMigrationUnlocked(m *masterPasswordMigration) error {
p := masterPasswordMigrationPath()
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
return fmt.Errorf("mkdir master password migration dir failed: %w", err)
}
data, err := gulu.JSON.MarshalIndentJSON(m, "", " ")
if err != nil {
return fmt.Errorf("marshal master password migration failed: %w", err)
}
return filelock.WriteFile(p, data)
}
func readMasterPasswordMigration() (*masterPasswordMigration, error) {
masterPasswordMigrationMu.Lock()
defer masterPasswordMigrationMu.Unlock()
return readMasterPasswordMigrationUnlocked()
}
func readMasterPasswordMigrationUnlocked() (*masterPasswordMigration, error) {
p := masterPasswordMigrationPath()
if !filelock.IsExist(p) {
return nil, nil
}
data, err := filelock.ReadFile(p)
if err != nil {
return nil, fmt.Errorf("read master password migration failed: %w", err)View on GitHub (pinned to 8641553a1f)
Solutions
- Inspect the wrapped error to find the offending field in masterPasswordMigration
- Ensure migration struct fields are JSON-serializable (no chan/func/cyclic refs)
- Rebuild the migration record from validated inputs rather than reusing a possibly-corrupt struct
- Update the kernel if a released version introduced the serialization defect
Example fix
// before: unmarshalable field
m.Callback = func() {} // marshal fails
// after: store only data
m.Unlocked = true
err := writeMasterPasswordMigration(m) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := gulu.JSON.MarshalIndentJSON(m, "", " "); err != nil {
return fmt.Errorf("migration record not serializable: %w", err)
} Try / catch
if err := writeMasterPasswordMigration(m); err != nil {
var tErr *json.UnsupportedTypeError
if errors.As(err, &tErr) {
log.Printf("bad migration field type: %v", tErr.Type)
}
return err
} Prevention
- Keep masterPasswordMigration fields restricted to JSON-safe types
- Add a unit test marshalling a fully populated migration record
- Rebuild migration state from validated inputs rather than reusing transient structs
When it happens
Trigger: writeMasterPasswordMigrationUnlocked marshals *masterPasswordMigration via gulu.JSON.MarshalIndentJSON and the marshaller returns an error — typically an unmarshalable nested value or a custom marshaller failure.
Common situations: A masterPasswordMigration struct extended with non-JSON-safe fields, or corrupted in-memory migration state assembled from a failed unlock operation.
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 legacy AI editor actions failed: %w
- unmarshal master password migration failed: %w
- marshal inline styles failed: %w
- marshal workspace conf [%s] failed: %s
- attribute view spec is too new
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/362174ecc6cd5bdb.
Report an issue: GitHub.