Skip to content

[BUG] Watch folder failure-tracking silently swallows DB errors #211

@deucebucket

Description

@deucebucket

What happened

While live-testing #209 on the maintainer instance (beta.147), a watch-folder item failed to move as expected (cross-filesystem hardlink blocked by the new pre-check). Log showed the clean error:

```
ERROR - Watch folder: Failed to move ...: Hard link failed: watch folder and library are on different filesystems...
```

But no `watch_folder_error` row was ever inserted into the `books` table — the user-facing UI never learns about the failure. The only signal to the user is the log line.

Root cause

`app.py:6918-6937` — the failure-tracking block for watch moves:

```python
else:
logger.error(f"Watch folder: Failed to move {item.name}: {error}")
# Issue #49: Track failed items in the database so user can see and fix them
watch_folder_processed.add(item_path)
try:
# Check if this item is already tracked
c.execute('SELECT id FROM books WHERE path = ?', (item_path,))
existing = c.fetchone()
if existing:
c.execute('''UPDATE books SET ...''', ...)
else:
c.execute('''INSERT INTO books ...''', ...)
conn.commit()
logger.info(f"Watch folder: Tracked failure for user review: {item.name}")
except Exception as db_err:
logger.debug(f"Watch folder: Could not track failure in DB: {db_err}") # <-- silently swallows at DEBUG level
```

Evidence from live test:

  • `logger.error` line: ✅ present
  • `logger.info("Tracked failure for user review")`: ❌ missing
  • `logger.debug("Could not track failure in DB")`: ❌ not visible at default log level

So we know the INSERT/UPDATE/commit block raises — we just don't know what, because `debug()` is suppressed.

Likely causes to investigate:

  • `existing['id']` on line 6927 — the cursor isn't using `sqlite3.Row`, so this would raise `TypeError: tuple indices must be integers` if `existing` is truthy. (Not the trigger for first-insert failures, but would bite on retry.)
  • `author` or `title` may be `None` if Layer 1 couldn't identify the book, and the schema might require non-null.
  • `conn` / `c` scope — are they still valid in this branch?
  • Possible sqlite lock or prior transaction not rolled back.

What to fix

  1. Raise the log level on the failure-tracking catch from `debug` to `warning` or `error` — silent swallowing is exactly the anti-pattern we just fixed in [BUG] when LM fails to create hardlinks, it copies and deletes original file #209 for a different reason. Users need to see this.
  2. Identify and fix whichever exception is actually being raised. Recommend running the reproduction below with `logging.DEBUG` enabled to capture the traceback, then fix the root cause.
  3. After the fix, the watch-folder UI should show failed items with an explicit `watch_folder_error` status and the error message, as [BUG] Too Many versions handing #49 originally intended.

Reproduction

On any dev instance:

  1. Set `watch_folder` to a path on filesystem A (e.g. `/tmp/watch`)
  2. Set `watch_output_folder` to a path on filesystem B (any other mount)
  3. Enable `watch_use_hard_links`
  4. Drop a small MP3 in the watch folder with recognizable metadata
  5. Wait for the watch scan to process it
  6. Observe: log shows the "different filesystems" error (beta.147+), but:
    • `SELECT * FROM books WHERE status='watch_folder_error'` returns nothing for this path
    • UI shows no failed item

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions