{"record":{"id":"e37d3fc83ea82306","repo":"cloudreve/cloudreve","slug":"failed-to-marshal-state-w","errorCode":null,"errorMessage":"failed to marshal state: %w","messagePattern":"failed to marshal state: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"application/migrator/migrator.go","lineNumber":158,"sourceCode":"\terr = model.Init()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tv4client, err := inventory.NewRawEntClient(m.l, m.dep.ConfigProvider())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tm.v4client = v4client\n\treturn m, nil\n}\n\n// saveState persists migration state to file\nfunc (m *Migrator) saveState() error {\n\tdata, err := json.Marshal(m.state)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal state: %w\", err)\n\t}\n\n\treturn os.WriteFile(m.statePath, data, 0644)\n}\n\n// loadState reads migration state from file\nfunc (m *Migrator) loadState() error {\n\tdata, err := os.ReadFile(m.statePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read state file: %w\", err)\n\t}\n\n\treturn json.Unmarshal(data, m.state)\n}\n\n// updateStep updates current step and persists state\nfunc (m *Migrator) updateStep(step int) error {\n\tm.state.Step = step","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/cloudreve/cloudreve/blob/20c95ad73f3a8bcb72887fea91ff31ab24fa1011/application/migrator/migrator.go#L140-L176","documentation":"saveState serializes the in-memory State with json.Marshal before writing it to disk. Every State field is a JSON-encodable primitive or map (ints, strings, map[int]bool, map[uint]string), so in the shipped code this error is effectively unreachable: encoding/json only fails on unsupported values such as funcs, channels, complex numbers, NaN floats, or cyclic pointer structures. Encountering it means a custom build added a non-serializable field to State.","triggerScenarios":"A fork or patch adds a field of type func(), chan, or complex128 to State; a float field holds NaN; State references a type whose custom MarshalJSON returns an error.","commonSituations":"Custom Cloudreve builds; third-party patches that extend the migration State struct without testing persistence.","solutions":["Inspect the State struct for func/chan/complex fields or custom MarshalJSON implementations and remove them.","Keep State limited to plain primitives, strings, slices, and maps of those.","Add a unit test that round-trips State through json.Marshal/json.Unmarshal to catch regressions in CI."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// CI regression guard: State must always be JSON-marshalable.\nfunc TestStateSerializable(t *testing.T) {\n\ts := &State{PolicyIDs: map[int]bool{1: true}, Step: StepGroup}\n\tif _, err := json.Marshal(s); err != nil {\n\t\tt.Fatalf(\"State is not serializable: %v\", err)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never add channels, funcs, complex numbers, or cyclic pointers to the persisted State struct.","Cover State serialization with a unit test in CI.","Treat any appearance of this error as a signal of a custom patch, not an operational issue."],"tags":["go","json","cloudreve","migration","state-management"],"backgroundTag":null,"analyzedSha":"20c95ad73f3a8bcb72887fea91ff31ab24fa1011","analyzedAt":"2026-08-16T01:42:55.403Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}