{"record":{"id":"8a8b563de96665ff","repo":"wavetermdev/waveterm","slug":"failed-to-unmarshal-backup-metadata-w","errorCode":null,"errorMessage":"failed to unmarshal backup metadata: %w","messagePattern":"failed to unmarshal backup metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/filebackup/filebackup.go","lineNumber":105,"sourceCode":"\treturn backupPath, nil\n}\n\nfunc RestoreBackup(backupFilePath string, restoreToFileName string) error {\n\tbackupData, err := os.ReadFile(backupFilePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read backup file: %w\", err)\n\t}\n\n\tmetadataPath := backupFilePath[:len(backupFilePath)-4] + \".json\"\n\tmetadataData, err := os.ReadFile(metadataPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read backup metadata: %w\", err)\n\t}\n\n\tvar metadata BackupMetadata\n\terr = json.Unmarshal(metadataData, &metadata)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to unmarshal backup metadata: %w\", err)\n\t}\n\n\tif metadata.FullPath != restoreToFileName {\n\t\treturn fmt.Errorf(\"backup metadata mismatch: expected %s, got %s\", restoreToFileName, metadata.FullPath)\n\t}\n\n\tvar perm os.FileMode\n\t_, err = fmt.Sscanf(metadata.Perm, \"%o\", &perm)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse file permissions: %w\", err)\n\t}\n\n\terr = os.WriteFile(restoreToFileName, backupData, perm)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to restore file: %w\", err)\n\t}\n\n\treturn nil","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/filebackup/filebackup.go#L87-L123","documentation":"RestoreBackup parses the metadata sidecar into BackupMetadata with json.Unmarshal. This error wraps unmarshal failure, meaning the .json content is not valid JSON for the expected schema (or was truncated/corrupted) and the restore is aborted.","triggerScenarios":"The .json sidecar is empty, truncated (e.g. from a crash mid-write), corrupted by an editor, or hand-edited into invalid JSON.","commonSituations":"System crash/power loss between WriteFile start and completion; manual inspection/edit of the metadata file that broke syntax; file corruption on disk.","solutions":["Validate the .json file content (e.g. jq . metadata.json) to see the syntax error.","Delete the corrupted backup pair and restore from a different backup of the same file in another dated directory.","Avoid hand-editing metadata sidecars; if inspection is needed, copy the file first.","Check the volume for filesystem corruption if multiple sidecars are corrupted."],"exampleFix":"// before\n{ \"fullpath\": \"/home/u/f.txt\", \"timestamp\": ... // truncated\n// after\ndelete the corrupt pair and pick another .bak/.json pair for the same file","handlingStrategy":"validation","validationCode":"metaData, err := os.ReadFile(strings.TrimSuffix(backupFilePath, \".bak\") + \".json\")\nif err == nil {\n    var probe map[string]any\n    if json.Unmarshal(metaData, &probe) != nil {\n        return fmt.Errorf(\"metadata sidecar is corrupt/invalid JSON\")\n    }\n}","typeGuard":null,"tryCatchPattern":"err := filebackup.RestoreBackup(backupPath, targetPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"unmarshal backup metadata\") {\n        return fmt.Errorf(\"backup metadata corrupted, pick another backup: %w\", err)\n    }\n    return err\n}","preventionTips":["Never hand-edit .json sidecars","Check for crash/truncation if backups were written during power loss","Validate sidecar JSON with jq before restoring manually","Run filesystem checks if multiple sidecars are corrupted"],"tags":["json","corruption","metadata","restore"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}