Skip to content

fix(octop): guard Path.stat() with OSError - closing the stat() defensive line (four files) - #2687

Closed
TrueFurina wants to merge 1 commit into
TencentCloud:mainfrom
TrueFurina:r80-stat-defensive-line-close
Closed

TrueFurina wants to merge 1 commit into
TencentCloud:mainfrom
TrueFurina:r80-stat-defensive-line-close

Conversation

@TrueFurina

Copy link
Copy Markdown

Summary

Close the Path.stat() defensive sweep with four files in one commit.

Changes

File Call site Fix approach On OSError
postgres_storage.py backup.stat().st_size _pg_backup_size() helper Returns 0
slim.py path.stat().st_size (backup progress) _safe_stat_size() helper Returns 0
profile_avatar.py path.stat().st_mtime (cache URL) Inline try/except Uses mtime=0
manage_skills.py child.stat().st_size (skill size check) Inline try/except Skips unreadable file

What is NOT fixed (intentionally)

  • skill_package_store.py L276: already wrapped by existing except OSError: continue (from round 74 refactor).
  • onnx_service.py L366: already wrapped by except OSError: in the surrounding loop.
  • sqlite_restore.py L31: already wrapped by except (ValueError, OSError): upstream.
  • json_file.py L101: POSIX-only (guarded by if os.name == 'posix') and operates on an existing path right before a rename-temp pattern; not worth the wrapper.
  • Inner temp-dir stat() calls inside office-automation skill scripts: those operate on freshly-unpacked docx/pptx/xlsx temp directories with no cross-process ACL risk.

Milestone

This closes out the Path.stat() defensive thread started in round 78. Combined with the earlier sweeps (suppress(Exception), Path.unlink(missing_ok=True), iterdir() OSError guard, glob()/
glob() OSError guard, and
ead_text()/
ead_bytes() OSError guard), every major filesystem call site across both Octop and harness is now defensively wrapped against Windows ACL/antivirus race conditions.

…sive line (four files)

The final four bare Path.stat() calls on user-data paths. On Windows, ACL restrictions or antivirus file locks can raise PermissionError during stat() even after existence checks pass.

1. postgres_storage.py - backup.stat().st_size in namespace_cleanup report. Added module-level _pg_backup_size() helper that catches OSError and returns 0.

2. slim.py - path.stat().st_size in slim-backup progress event. Added module-level _safe_stat_size() helper that catches OSError and returns 0.

3. profile_avatar.py - path.stat().st_mtime in profile_avatar_url(). Inline try/except OSError, default mtime=0 for cache-busting URL.

4. manage_skills.py - child.stat().st_size in skill size validation loop. Inline try/except OSError, skip unreadable file.

With this commit, every bare Path.stat() on user-controllable paths across both repos is now wrapped in try/except OSError. The remaining stat() calls are either already inside broad except blocks, on immutable package resources, or on internal temp directories freshly created by the process.
@jubaoliang

Copy link
Copy Markdown
Collaborator

🔍 Automated Review Findings

  • 🧱 No test changes detected: add tests for new features, regression tests for bug fixes

Please address the above and @ me for re-review.

@jubaoliang jubaoliang closed this Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants