Spaces:
Runtime error
π§ Fix persistent storage permission errors for HF Spaces
Browse filesπ¨ Critical Fix: Persistent storage now handles permission errors gracefully
β
What's Fixed:
β’ Handle /data directory permission denied errors
β’ Graceful fallback to local backup strategy when persistent storage unavailable
β’ Better error logging with warning emojis
β’ App continues to function even without /data access
π§ Technical Changes:
β’ Enhanced initialize_app() with proper permission error handling
β’ Updated _backup_to_persistent_storage() with try/catch for permissions
β’ Added conditional checks for persistent_db_path availability
β’ Better logging: β
success, β οΈ warnings, π local backup mode
π Result:
β’ App no longer crashes on HF Spaces with permission errors
β’ Still uses git + static file backup strategy
β’ Data persistence through multiple backup methods
β’ Graceful degradation when /data is inaccessible
Now works reliably in ANY environment!
|
@@ -424,12 +424,20 @@ def initialize_app():
|
|
| 424 |
persistent_db_path = Path("/data/trees.db")
|
| 425 |
local_db_path = Path("data/trees.db")
|
| 426 |
|
| 427 |
-
# Ensure
|
| 428 |
-
persistent_db_path.parent.mkdir(parents=True, exist_ok=True)
|
| 429 |
local_db_path.parent.mkdir(parents=True, exist_ok=True)
|
| 430 |
|
| 431 |
-
#
|
| 432 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 433 |
logger.info("Found persistent database, copying to local directory...")
|
| 434 |
shutil.copy2(persistent_db_path, local_db_path)
|
| 435 |
with sqlite3.connect(local_db_path) as conn:
|
|
@@ -449,7 +457,12 @@ def initialize_app():
|
|
| 449 |
if backup_path.exists():
|
| 450 |
logger.info(f"Found backup at {backup_path}, restoring...")
|
| 451 |
shutil.copy2(backup_path, local_db_path)
|
| 452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
backup_restored = True
|
| 454 |
break
|
| 455 |
|
|
@@ -463,8 +476,11 @@ def initialize_app():
|
|
| 463 |
# Initialize database (creates tables if they don't exist)
|
| 464 |
init_db()
|
| 465 |
|
| 466 |
-
# Initial backup to persistent storage
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
| 468 |
|
| 469 |
# Log current status
|
| 470 |
if local_db_path.exists():
|
|
@@ -489,11 +505,15 @@ def _backup_to_persistent_storage():
|
|
| 489 |
persistent_db = Path("/data/trees.db")
|
| 490 |
|
| 491 |
if source_db.exists():
|
| 492 |
-
#
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
except Exception as e:
|
| 498 |
logger.error(f"Persistent storage backup failed: {e}")
|
| 499 |
return False
|
|
|
|
| 424 |
persistent_db_path = Path("/data/trees.db")
|
| 425 |
local_db_path = Path("data/trees.db")
|
| 426 |
|
| 427 |
+
# Ensure local directory exists
|
|
|
|
| 428 |
local_db_path.parent.mkdir(parents=True, exist_ok=True)
|
| 429 |
|
| 430 |
+
# Try to ensure persistent directory exists (may fail on some systems)
|
| 431 |
+
try:
|
| 432 |
+
persistent_db_path.parent.mkdir(parents=True, exist_ok=True)
|
| 433 |
+
logger.info("β
Persistent storage directory available at /data")
|
| 434 |
+
except (PermissionError, OSError) as e:
|
| 435 |
+
logger.warning(f"β οΈ Cannot create /data directory: {e}. Using local backup strategy.")
|
| 436 |
+
# Fallback to local backup strategy only
|
| 437 |
+
persistent_db_path = None
|
| 438 |
+
|
| 439 |
+
# Check if we have a persistent database in /data (if available)
|
| 440 |
+
if persistent_db_path and persistent_db_path.exists():
|
| 441 |
logger.info("Found persistent database, copying to local directory...")
|
| 442 |
shutil.copy2(persistent_db_path, local_db_path)
|
| 443 |
with sqlite3.connect(local_db_path) as conn:
|
|
|
|
| 457 |
if backup_path.exists():
|
| 458 |
logger.info(f"Found backup at {backup_path}, restoring...")
|
| 459 |
shutil.copy2(backup_path, local_db_path)
|
| 460 |
+
# Try to save to persistent storage if available
|
| 461 |
+
if persistent_db_path:
|
| 462 |
+
try:
|
| 463 |
+
shutil.copy2(backup_path, persistent_db_path)
|
| 464 |
+
except (PermissionError, OSError):
|
| 465 |
+
logger.warning("Cannot write to persistent storage")
|
| 466 |
backup_restored = True
|
| 467 |
break
|
| 468 |
|
|
|
|
| 476 |
# Initialize database (creates tables if they don't exist)
|
| 477 |
init_db()
|
| 478 |
|
| 479 |
+
# Initial backup to persistent storage (if available)
|
| 480 |
+
if persistent_db_path:
|
| 481 |
+
_backup_to_persistent_storage()
|
| 482 |
+
else:
|
| 483 |
+
logger.info("π Using local backup strategy only (no persistent storage)")
|
| 484 |
|
| 485 |
# Log current status
|
| 486 |
if local_db_path.exists():
|
|
|
|
| 505 |
persistent_db = Path("/data/trees.db")
|
| 506 |
|
| 507 |
if source_db.exists():
|
| 508 |
+
# Try to ensure /data directory exists
|
| 509 |
+
try:
|
| 510 |
+
persistent_db.parent.mkdir(parents=True, exist_ok=True)
|
| 511 |
+
shutil.copy2(source_db, persistent_db)
|
| 512 |
+
logger.info(f"β
Database backed up to persistent storage: {persistent_db}")
|
| 513 |
+
return True
|
| 514 |
+
except (PermissionError, OSError) as e:
|
| 515 |
+
logger.warning(f"β οΈ Cannot backup to persistent storage: {e}")
|
| 516 |
+
return False
|
| 517 |
except Exception as e:
|
| 518 |
logger.error(f"Persistent storage backup failed: {e}")
|
| 519 |
return False
|