Skip to content

Replace silent except Exception: pass with structured logging in workspace/bubble paths (closes #66)#76

Open
bradjin8 wants to merge 6 commits into
masterfrom
feat/replace-except-pass
Open

Replace silent except Exception: pass with structured logging in workspace/bubble paths (closes #66)#76
bradjin8 wants to merge 6 commits into
masterfrom
feat/replace-except-pass

Conversation

@bradjin8
Copy link
Copy Markdown
Collaborator

@bradjin8 bradjin8 commented May 25, 2026

Summary

Closes #66 . Replaces bare except Exception: pass in workspace, composer, and bubble iteration loops with logging.warning() (or logging.error() for global DB load failures) so schema/parse failures are observable instead of silently dropping records.

  • Services: workspace_listing, workspace_tabs, workspace_resolver — module loggers, Composer.from_dict on listing (aligned with tabs), warnings include model/key and exception message
  • API: search, logs, workspaces — same pattern on workspace.json reads, composer mapping, legacy search, and bubble row decode
  • Tests: tests/test_parse_failure_logging.py — two pytest caplog tests (listing composer drift, tabs bubble drift)
  • CI: pytest step runs the new test file

Control flow unchanged: bad rows are still skipped; endpoints do not 500 on a single malformed record.

print() for schema drift in api/search / api/composers is intentionally unchanged (follow-up).

Eval / tracker

Addresses baseline Test 11 (silent except-pass in workspace/bubble loops) and §5.3 of cursor-chat-browser-python-eval. Partially improves Test 10 (parse failures now logged in services + search/logs paths; print-based drift messages deferred).

Test plan

  • python -m pytest tests/test_parse_failure_logging.py -v
  • python -m unittest tests.test_project_layouts_dict_shape tests.test_workspace_listing_sql_errors tests.test_workspace_tabs_malformed_nested tests.test_invalid_workspace_aliases -v
  • Full CI green on PR

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling and structured warning logs across search, workspace listing, workspace resolution and tab assembly; failures now emit warnings (with relevant IDs) instead of failing silently.
    • Malformed or missing workspace/composer/bubble records are skipped with warnings, increasing robustness and consistent results.
  • Tests

    • Added tests validating warning logs for various parse/format failures and NULL/malformed records.
  • Chores

    • Updated a pinned dependency.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces silent exception handling and prints with module-level structured logging across APIs and services, adding warnings that include workspace/composer/bubble identifiers and exception details; tests assert WARNING logs for several parse-failure scenarios.

Changes

Parse failure logging refactor

Layer / File(s) Summary
API routes: error logging for logs, search, and workspaces endpoints
api/logs.py, api/search.py, api/workspaces.py
Replaces silent exception suppression with _logger.warning across endpoints for bubble JSON decode, workspace.json read, composer processing, legacy workspace traversal, and CLI session blob traversal.
Workspace listing service: composer validation and logging
services/workspace_listing.py
Adds module logger and refactors composer parsing to json.loads and Composer.from_dict(...), emitting warnings on decode/type/schema errors; logs workspace.json and state.vscdb read/mtime failures and replaces print with _logger.warning.
Workspace resolver service: helper functions error logging
services/workspace_resolver.py
Adds module logger and emits warnings when reading/parsing workspace.json across helper functions; logs Composer decode errors and skips non-dict composer JSON payloads.
Workspace tabs service: schema validation and processing error logging
services/workspace_tabs.py
Adds module logger and replaces prints/silent suppression with warnings: skip NULL-valued rows with warning, log JSON decode failures (id/key + raw value + error), log from_dict SchemaError for Bubble/Composer, and log per-composer processing exceptions.
New test module: parse-failure logging verification
tests/test_parse_failure_logging.py
Adds four tests that seed temporary Cursor DBs with malformed Composer/Bubble records and assert services.workspace_listing / services.workspace_tabs emit WARNING logs for composer schema drift, bubble/composer JSON decode failures, and bubble schema drift.
Test updates: regression coverage for non-dict composer and null bubble
tests/test_invalid_workspace_aliases.py, tests/test_workspace_tabs_null_bubble.py
Adds test ensuring non-dict composer JSON is skipped without crash; updates null-bubble regression test to assert a warning is logged for NULL-valued bubble rows.
Dependency update: click version bump
requirements-lock.txt
Updates pinned click from 8.4.0 to 8.4.1 (via flask).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • timon0305
  • clean6378-max-it
  • wpak-ai

Poem

🐰 Hop, hop — a warning in the log,
No silent fails left in the fog.
Composer, bubble, workspace named,
Each parse fallacy is framed.
Tests cheer loud — the rabbit nods with glee.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning All changes are directly related to issue #66. The only tangential change is the click dependency bump in requirements-lock.txt, which is a transitive dependency update unrelated to the logging objective. Remove or justify the click dependency version bump (8.4.0 → 8.4.1) in requirements-lock.txt as it is out of scope for the logging refactor objective.
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective of replacing silent exception handling with structured logging across workspace and bubble paths, and references issue #66.
Linked Issues check ✅ Passed All acceptance criteria from issue #66 are met: silent except blocks replaced with structured logging, module-level loggers added, log messages include model/key/exception, tests added with caplog assertions, and control flow unchanged.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/replace-except-pass

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/workspace_resolver.py`:
- Around line 337-345: The code currently calls json.loads(row["value"]) into cd
and then passes cd to _determine_project_for_conversation which assumes a dict;
guard against non-dict JSON by checking the type of cd after json.loads (e.g.,
isinstance(cd, dict)); if cd is not a dict, log a warning referencing cid and
the actual type/value and continue (so assemble_workspace_tabs/alias inference
won't crash), then only call _determine_project_for_conversation(cd, ...) when
cd is a dict.

In `@services/workspace_tabs.py`:
- Around line 127-131: The code currently swallows JSON decode failures inside
_try_loads_kv_value and only logs SchemaError later (e.g., in the Bubble parse
path that logs "Failed to parse Bubble from bubbleId:%s"), so malformed JSON is
silently skipped; fix by surfacing JSON decoding errors at the bubble/composer
call sites: replace the single call to _try_loads_kv_value(...) with an explicit
json.loads(...) wrapped in try/except JSONDecodeError (or change
_try_loads_kv_value to return the decode exception) and when a JSONDecodeError
occurs call _logger.warning including the context keys (bubbleId or
composerData), the raw value, and the exception, then skip processing; apply the
same pattern for the composerData parse site referenced in the comment so decode
errors are logged for both locations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b02d469-09c7-4fb6-ba44-8400fa6a55b0

📥 Commits

Reviewing files that changed from the base of the PR and between 731c1e1 and 238a7b3.

📒 Files selected for processing (8)
  • .github/workflows/tests.yml
  • api/logs.py
  • api/search.py
  • api/workspaces.py
  • services/workspace_listing.py
  • services/workspace_resolver.py
  • services/workspace_tabs.py
  • tests/test_parse_failure_logging.py

Comment thread services/workspace_resolver.py
Comment thread services/workspace_tabs.py
bradjin8 added 2 commits May 25, 2026 10:59
Linux CI pip-compile now resolves click==8.4.1 within the flask bound; the lock still pinned 8.4.0, which failed the lockfile freshness job.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/workspace_resolver.py (1)

337-344: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace bare Exception with specific exception types.

Line 338 catches bare Exception, which violates the PR objective to remove all except Exception: pass patterns. json.loads can raise JSONDecodeError, TypeError, or ValueError; catch these specific types instead.

🔧 Proposed fix
         try:
             cd = json.loads(row["value"])
-        except Exception as e:
+        except (json.JSONDecodeError, TypeError, ValueError) as e:
             _logger.warning(
                 "Failed to decode Composer from composerData:%s: %s",
                 cid,
                 e,
             )
             continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/workspace_resolver.py` around lines 337 - 344, The current except
block catches a bare Exception after calling json.loads(row["value"]); replace
it with a specific exception tuple to only handle JSONDecodeError, TypeError,
and ValueError (e.g., except (json.JSONDecodeError, TypeError, ValueError) as e)
so only relevant decode/type errors are caught, and keep the existing
_logger.warning(..., cid, e) and continue logic intact; ensure
json.JSONDecodeError is referenced correctly (or imported from json.decoder) if
your Python version requires it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/workspace_tabs.py`:
- Around line 117-126: The json.loads(row["value"]) call in
services/workspace_tabs.py can raise TypeError when row["value"] is None (NULL)
and ValueError for other invalid inputs, but the except only handles
json.JSONDecodeError; update the parsing logic around parsed =
json.loads(row["value"]) (the block that logs "Failed to decode Bubble...") to
also catch TypeError and ValueError (or alternatively guard with an explicit
None check before calling json.loads) and include the same warning/logging
behavior and continue, ensuring the failure mode matches the previous
_try_loads_kv_value behavior.
- Around line 195-204: The JSON parse for composer data can raise TypeError when
row["value"] is None; update the parsing in the try/except around
json.loads(row["value"]) (the block referencing composer_id and row["value"]) to
guard against None by either checking row["value"] is not None before calling
json.loads or by expanding the except to catch TypeError alongside
json.JSONDecodeError, and keep the existing _logger.warning and continue
behavior when parsing fails.

In `@tests/test_parse_failure_logging.py`:
- Line 140: The test unpacks a returned tuple from assemble_workspace_tabs into
payload and status but never uses payload, triggering Ruff RUF059; change the
unused variable to a conventional ignored name (e.g., _payload or _) in the test
calls to assemble_workspace_tabs (the invocations around payload, status =
assemble_workspace_tabs(...) at the two occurrences) so only the used status is
kept and the linter warning is resolved.

---

Outside diff comments:
In `@services/workspace_resolver.py`:
- Around line 337-344: The current except block catches a bare Exception after
calling json.loads(row["value"]); replace it with a specific exception tuple to
only handle JSONDecodeError, TypeError, and ValueError (e.g., except
(json.JSONDecodeError, TypeError, ValueError) as e) so only relevant decode/type
errors are caught, and keep the existing _logger.warning(..., cid, e) and
continue logic intact; ensure json.JSONDecodeError is referenced correctly (or
imported from json.decoder) if your Python version requires it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10504aeb-e19a-4d6e-8858-080ff950c843

📥 Commits

Reviewing files that changed from the base of the PR and between d55881f and 4e7a23b.

📒 Files selected for processing (4)
  • services/workspace_resolver.py
  • services/workspace_tabs.py
  • tests/test_invalid_workspace_aliases.py
  • tests/test_parse_failure_logging.py

Comment thread services/workspace_tabs.py
Comment thread services/workspace_tabs.py
Comment thread tests/test_parse_failure_logging.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/workspace_tabs.py`:
- Around line 117-118: Replace the silent skip for rows with a None payload by
emitting a warning that includes identifying row metadata: instead of just "if
row['value'] is None: continue", call the module logger (e.g., logger.warning or
self.logger.warning) and include row.get("key") or other identifying fields and
the full row (or its id) in the message, then continue; apply the same change to
the second occurrence around the other None-check so malformed NULL KV rows are
logged for observability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4617c257-c8c7-410f-9589-1c61bffae090

📥 Commits

Reviewing files that changed from the base of the PR and between 4e7a23b and d23fe71.

📒 Files selected for processing (3)
  • services/workspace_tabs.py
  • tests/test_parse_failure_logging.py
  • tests/test_workspace_tabs_null_bubble.py

Comment thread services/workspace_tabs.py
@bradjin8 bradjin8 self-assigned this May 25, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/workspace_tabs.py (1)

123-126: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Catch non-JSONDecode failures when decoding Bubble/Composer KV values
In services/workspace_tabs.py, both json.loads(row["value"]) sites (Bubble and Composer) only catch json.JSONDecodeError; json.loads can raise TypeError when SQLite returns a non-JSON payload type (and that would escape, potentially breaking /tabs). Reuse _try_loads_kv_value (already catches json.JSONDecodeError/TypeError/ValueError) or broaden the exception handling.

💡 Minimal hardening patch
-                except json.JSONDecodeError as e:
+                except (json.JSONDecodeError, TypeError, ValueError) as e:
                     _logger.warning(
                         "Failed to decode Bubble from %s: %s (value: %r)",
                         row["key"],
                         e,
                         row["value"],
                     )
                     continue
@@
-            except json.JSONDecodeError as e:
+            except (json.JSONDecodeError, TypeError, ValueError) as e:
                 _logger.warning(
                     "Failed to decode Composer from composerData:%s: %s (value: %r)",
                     composer_id,
                     e,
                     row["value"],
                 )
                 continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/workspace_tabs.py` around lines 123 - 126, The JSON decoding in
services/workspace_tabs.py currently only catches json.JSONDecodeError around
json.loads(row["value"]); change this to use the existing _try_loads_kv_value
helper (which already handles JSONDecodeError/TypeError/ValueError) or expand
the except clause to also catch TypeError and ValueError so non-string SQLite
payloads don't raise and break /tabs; update both Bubble and Composer json.loads
sites and ensure the warning log still includes context (row key/id) as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@services/workspace_tabs.py`:
- Around line 123-126: The JSON decoding in services/workspace_tabs.py currently
only catches json.JSONDecodeError around json.loads(row["value"]); change this
to use the existing _try_loads_kv_value helper (which already handles
JSONDecodeError/TypeError/ValueError) or expand the except clause to also catch
TypeError and ValueError so non-string SQLite payloads don't raise and break
/tabs; update both Bubble and Composer json.loads sites and ensure the warning
log still includes context (row key/id) as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f59ff990-e7bc-4b66-9406-ad43f7246a72

📥 Commits

Reviewing files that changed from the base of the PR and between d23fe71 and 2cc885f.

📒 Files selected for processing (2)
  • services/workspace_tabs.py
  • tests/test_workspace_tabs_null_bubble.py

@bradjin8 bradjin8 requested a review from timon0305 May 25, 2026 15:51
Comment thread services/workspace_tabs.py Outdated
Comment thread services/workspace_resolver.py Outdated
Comment thread services/workspace_listing.py Outdated
@bradjin8 bradjin8 requested a review from timon0305 May 25, 2026 18:41
@timon0305 timon0305 requested a review from wpak-ai May 25, 2026 18:53
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.

Replace except-pass with structured logging at parse sites

2 participants