{"record":{"id":"362174ecc6cd5bdb","repo":"siyuan-note/siyuan","slug":"marshal-master-password-migration-failed-w","errorCode":null,"errorMessage":"marshal master password migration failed: %w","messagePattern":"marshal master password migration failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":544,"sourceCode":"\nfunc masterPasswordMigrationPath() string {\n\treturn filepath.Join(util.DataDir, \".siyuan\", \"master-password-migration.json\")\n}\n\nfunc writeMasterPasswordMigration(m *masterPasswordMigration) error {\n\tmasterPasswordMigrationMu.Lock()\n\tdefer masterPasswordMigrationMu.Unlock()\n\treturn writeMasterPasswordMigrationUnlocked(m)\n}\n\nfunc writeMasterPasswordMigrationUnlocked(m *masterPasswordMigration) error {\n\tp := masterPasswordMigrationPath()\n\tif err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {\n\t\treturn fmt.Errorf(\"mkdir master password migration dir failed: %w\", err)\n\t}\n\tdata, err := gulu.JSON.MarshalIndentJSON(m, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal master password migration failed: %w\", err)\n\t}\n\treturn filelock.WriteFile(p, data)\n}\n\nfunc readMasterPasswordMigration() (*masterPasswordMigration, error) {\n\tmasterPasswordMigrationMu.Lock()\n\tdefer masterPasswordMigrationMu.Unlock()\n\treturn readMasterPasswordMigrationUnlocked()\n}\n\nfunc readMasterPasswordMigrationUnlocked() (*masterPasswordMigration, error) {\n\tp := masterPasswordMigrationPath()\n\tif !filelock.IsExist(p) {\n\t\treturn nil, nil\n\t}\n\tdata, err := filelock.ReadFile(p)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read master password migration failed: %w\", err)","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/crypto.go#L526-L562","documentation":"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.","triggerScenarios":"writeMasterPasswordMigrationUnlocked marshals *masterPasswordMigration via gulu.JSON.MarshalIndentJSON and the marshaller returns an error — typically an unmarshalable nested value or a custom marshaller failure.","commonSituations":"A masterPasswordMigration struct extended with non-JSON-safe fields, or corrupted in-memory migration state assembled from a failed unlock operation.","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"],"exampleFix":"// before: unmarshalable field\nm.Callback = func() {} // marshal fails\n// after: store only data\nm.Unlocked = true\nerr := writeMasterPasswordMigration(m)","handlingStrategy":"try-catch","validationCode":"if _, err := gulu.JSON.MarshalIndentJSON(m, \"\", \"  \"); err != nil {\n    return fmt.Errorf(\"migration record not serializable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := writeMasterPasswordMigration(m); err != nil {\n    var tErr *json.UnsupportedTypeError\n    if errors.As(err, &tErr) {\n        log.Printf(\"bad migration field type: %v\", tErr.Type)\n    }\n    return err\n}","preventionTips":["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"],"tags":["go","json","serialization","migration"],"backgroundTag":"json-marshal-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}