POST /api/libraries/:id/issues/:issueId/retry (admin, family-lens gated via the existing gateIssue) re-runs the work that produced an open issue — deliberately NOT a library-wide rescan. Two shapes mirror the two ledger entry kinds: - item-backed issues rescan their media item through the book-detail RescanMediaItem mechanism (self-resolving folders, multi-file audiobook routing, write-after-success guards) and then close the issue (RetryMediaItemIssue); - row-less import_failed issues re-import the single file through the watcher's standalone processMediaFile path (RetryFailedImport: folders resolved RescanMediaItem-style so paths stay library-root-relative), whose create-path self-heal plus an explicit path resolve closes the issue even when the content was already imported by a prior attempt. Failures return the REAL underlying error so the UI can show why the issue still exists; a vanished file is a 409 (ErrRetryFileMissing); already-resolved issues reject re-retry. Docs + bruno mirrors regenerated for the new route (the generator's seq renumbering touches three unrelated bruno files as fallout; openapi gains the path and the date bump), and the docs schema registry gains the retry entry so TestDocsMatchRoutes passes.
42 lines
1.5 KiB
Markdown
42 lines
1.5 KiB
Markdown
---
|
|
method: POST
|
|
path: /api/libraries/:id/issues/:issueId/retry
|
|
auth: jwt+admin
|
|
area: libraries
|
|
---
|
|
<!-- source: internal/handlers/processing_issues.go RetryProcessingIssue -->
|
|
|
|
# Retry Processing Issue
|
|
|
|
Re-runs the work that produced an open issue through the individual
|
|
scanner — deliberately NOT a library-wide rescan. Two shapes:
|
|
|
|
- **Item-backed issues** (media item exists): the item is rescanned via
|
|
the same mechanism as the book-detail Rescan action — self-resolving
|
|
folders, multi-file audiobook routing, write-after-success guards.
|
|
- **Row-less `import_failed` issues** (no media item): the single file
|
|
is re-imported through the scanner's standalone per-file path.
|
|
|
|
On success the issue is closed. On failure the response carries the REAL
|
|
error (e.g. the underlying SQL failure), so the UI can show why the issue
|
|
still exists. The issue's library must be in the requester's visible set.
|
|
|
|
## Example response
|
|
|
|
```json example-response
|
|
{
|
|
"success": true,
|
|
"message": "File imported; issue resolved"
|
|
}
|
|
```
|
|
|
|
## Errors
|
|
|
|
| Status | Body | When |
|
|
| ------ | ---- | ---- |
|
|
| 400 | `{"error": "Invalid issue ID"}` | malformed path param |
|
|
| 403 | — | issue's library not in requester's visible set |
|
|
| 404 | `{"error": "Issue not found"}` | no such issue |
|
|
| 409 | `{"error": "Issue is already resolved"}` / `{"error": "media file not found on disk: …"}` | nothing to retry, or the file vanished |
|
|
| 500 | `{"error": "…"}` | the retried work failed — body carries the underlying error |
|