{"record":{"id":"c01504d0e04722f2","repo":"wavetermdev/waveterm","slug":"failed-to-parse-file-permissions-w","errorCode":null,"errorMessage":"failed to parse file permissions: %w","messagePattern":"failed to parse file permissions: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/filebackup/filebackup.go","lineNumber":115,"sourceCode":"\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\n}\n\nfunc CleanupOldBackups() error {\n\tbackupBaseDir := filepath.Join(wavebase.GetWaveCachesDir(), \"waveai-backups\")\n\n\tif _, err := os.Stat(backupBaseDir); os.IsNotExist(err) {\n\t\treturn nil\n\t}\n\n\tentries, err := os.ReadDir(backupBaseDir)","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/filebackup/filebackup.go#L97-L133","documentation":"RestoreBackup parses the octal permission string recorded in metadata.Perm (formatted as %04o at backup time) into an os.FileMode using fmt.Sscanf(\"%o\"). This error wraps Sscanf failing, meaning the Perm string is missing, empty, or not valid octal.","triggerScenarios":"The .json sidecar has a missing/empty 'perm' field or a non-octal value — from a corrupted, truncated, or hand-edited metadata file, or a sidecar produced by incompatible code.","commonSituations":"Hand-edited metadata where perm was changed to e.g. \"rwxr-xr-x\" or \"\"; truncated JSON that unmarshaled to a zero-value struct with empty Perm; schema drift between backup writers.","solutions":["Inspect the 'perm' field in the .json sidecar and ensure it is a 3-4 digit octal string like \"0644\".","Fix the perm value in the sidecar to the correct octal mode (or recreate the backup pair).","Consider using strconv.ParseUint(metadata.Perm, 8, 32) in caller-side validation to pre-check before restore.","Verify the sidecar came from the same version of the backup code (Perm format %04o)."],"exampleFix":"// before\n\"perm\": \"rw-r--r--\"   // not octal, Sscanf %o fails\n// after\n\"perm\": \"0644\"        // valid octal","handlingStrategy":"validation","validationCode":"metaData, _ := os.ReadFile(strings.TrimSuffix(backupFilePath, \".bak\") + \".json\")\nvar meta struct{ Perm string `json:\"perm\"` }\njson.Unmarshal(metaData, &meta)\nif _, err := strconv.ParseUint(meta.Perm, 8, 32); err != nil {\n    return fmt.Errorf(\"invalid perm field %q in metadata\", meta.Perm)\n}","typeGuard":null,"tryCatchPattern":"err := filebackup.RestoreBackup(backupPath, targetPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"parse file permissions\") {\n        return fmt.Errorf(\"metadata perm field invalid; fix sidecar or pick another backup: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep the 'perm' field as a 3-4 digit octal string (e.g. \"0644\")","Don't translate perms to symbolic form in sidecars","Validate sidecars before restoring after manual inspection","Ensure backups are read back by the same schema version that wrote them"],"tags":["permissions","parsing","metadata","restore"],"backgroundTag":"invalid-permission-format","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}