Skip to content

fix(kanban): delete partial attachment file on OSError during upload#35596

Open
sprmn24 wants to merge 1 commit into
NousResearch:mainfrom
sprmn24:fix/kanban-eklenti-oserror-orphan
Open

fix(kanban): delete partial attachment file on OSError during upload#35596
sprmn24 wants to merge 1 commit into
NousResearch:mainfrom
sprmn24:fix/kanban-eklenti-oserror-orphan

Conversation

@sprmn24

@sprmn24 sprmn24 commented May 31, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

upload_task_attachment() in plugins/kanban/dashboard/plugin_api.py writes
the uploaded blob directly to dest_path. When an OSError occurs mid-write
(disk full, permission denied, etc.) the handler converts it to HTTP 500 but
does not remove dest_path, leaving a partial file on disk with no matching
row in task_attachments.

The size-limit (413) path immediately above already does the right thing:

dest_path.unlink(missing_ok=True)
raise HTTPException(status_code=413, ...)

The OSError path was missing the same one-line cleanup.

Related Issue

Fixes #35338 (follow-up — the attachment upload endpoint introduced in #35395
did not clean up on write failure)

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • plugins/kanban/dashboard/plugin_api.py: add dest_path.unlink(missing_ok=True)
    before re-raising in the except OSError handler of upload_task_attachment()

How to Test

  1. Upload a file to a kanban task via the dashboard
  2. Simulate a disk-full error (e.g. mock out.write to raise OSError)
  3. Before fix: a partial file is left under ~/.hermes/kanban/attachments/<task_id>/
  4. After fix: no file remains; the HTTP 500 is returned cleanly

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Windows 11

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

One-line diff — only the cleanup path changes, happy path is unaffected.

upload_task_attachment() writes the blob directly to dest_path. When an
OSError occurs mid-write (disk full, permission denied), the except block
converted the error to HTTPException but did not clean up dest_path,
leaving a partial file on disk with no matching DB record.

Add dest_path.unlink(missing_ok=True) before re-raising so the orphan
file is removed on every write failure. Mirrors the cleanup already
present in the size-limit (413) path above it.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins labels May 31, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Review

A one-line fix that prevents orphaned partial attachment files on OSError during kanban upload — matching the existing cleanup pattern in the size-limit (413) path.

✅ Looks Good

  • Correct fix: Exactly matches the existing dest_path.unlink(missing_ok=True) pattern used by the 413 handler.
  • Zero risk: Only adds cleanup on error path; happy path is completely untouched.
  • Well-documented: Clear PR body explaining the bug and fix.

Reviewed by Hermes Agent (cron job)

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Reviewed Changes

  • plugins/kanban/dashboard/plugin_api.py:upload_task_attachment — Added dest_path.unlink(missing_ok=True) in the OSError handler to clean up partial attachment files.

✅ Looks Good

  • Correctness: When an OSError occurs during attachment upload (e.g. disk full, quota exceeded), the partially written file at dest_path remains on disk. This adds a cleanup that removes the orphaned file. Using missing_ok=True avoids a second OSError if the file doesn't exist yet.
  • Minimal change: Single line addition. Low risk.
  • No security concerns: No injection vectors or credential exposure.
  • Edge cases: missing_ok=True (Python 3.8+) handles the case where the file was never created before the error. The exception is still re-raised, so the caller sees the original error.

Reviewed by Hermes Agent

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Overview

Clean one-line fix adding missing dest_path.unlink(missing_ok=True) in the except OSError handler of upload_task_attachment(). Prevents partial orphan files on failed uploads — mirrors the existing cleanup in the size-limit (413) path.

Looks Good

  • One-line change, precisely targeted
  • Uses missing_ok=True — safe for concurrent access
  • Mirrors existing pattern in the same function
  • Low blast radius

Reviewed by Hermes Agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File upload in Kanban tasks

3 participants