Skip to content

fix: narrow bare except Exception to specific types where safe#54

Merged
bensig merged 1 commit into
MemPalace:mainfrom
adv3nt3:fix/narrow-exception-handling
Apr 7, 2026
Merged

fix: narrow bare except Exception to specific types where safe#54
bensig merged 1 commit into
MemPalace:mainfrom
adv3nt3:fix/narrow-exception-handling

Conversation

@adv3nt3

@adv3nt3 adv3nt3 commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Replace broad except Exception with specific exception types in 6 sites where the expected failure mode is well-defined:

  • normalize.py: OSError for file read, ImportError for optional spellcheck import
  • miner.py: OSError for filepath.read_text()
  • entity_detector.py: OSError for file read in scan loop
  • convo_miner.py: (OSError, ValueError) for normalize() which reads and parses files
  • entity_registry.py: (URLError, OSError, JSONDecodeError, KeyError) for Wikipedia lookup fallback

What's NOT changed (and why)

  • ChromaDB sites (~30): chromadb.errors defines NotFoundError, DuplicateIDError, InvalidDimensionException, etc. (verified from source). Narrowing those sites requires importing from chromadb.errors and validating across supported versions (>=0.4.0) — left for a follow-up.
  • MCP server handlers: Intentionally broad for resilience — must return error messages to clients, not crash.
  • file_already_mined checks: Return False on any error is correct resilience behavior.

Changes

5 files changed, 6 lines modified. Each except Exception replaced with the narrowest type(s) that cover the actual failure modes.

Test plan

  • ruff check passes clean on all 5 files
  • ruff format --check already formatted
  • python3 -m py_compile compiles OK for all 5 files
  • Pyright reports 0 new diagnostics
  • Exception types verified: OSError covers all file I/O, ImportError covers optional imports, urllib.error.URLError covers network failures

Replace broad except Exception with specific exception types in 6
sites where the expected failure mode is well-defined:

- normalize.py: OSError for file read, ImportError for optional import
- miner.py: OSError for file read_text
- entity_detector.py: OSError for file read in scan loop
- convo_miner.py: (OSError, ValueError) for normalize which reads
  and parses files
- entity_registry.py: (URLError, OSError, JSONDecodeError, KeyError)
  for Wikipedia lookup fallback

ChromaDB except Exception sites (~30) are left broad for now.
chromadb.errors defines NotFoundError, DuplicateIDError,
InvalidDimensionException etc., but narrowing those sites requires
importing from chromadb.errors and validating across supported
versions (>=0.4.0). MCP server handlers also left broad for
resilience.
@bensig bensig merged commit 6af6fe3 into MemPalace:main Apr 7, 2026
CuraIQ-Dev pushed a commit to Finimo-Solutions/mempalace-nexus-backend that referenced this pull request Apr 21, 2026
…LOW + 2 CodeRabbit minor)

Adversarial R1 + CodeRabbit:

- HIGH (adv): where_document={'$contains': 'foo'} crashed _translate_where
  (top-level $op rejected) making the keyword-boost path unreachable.
  Fix: _normalize_where_document rewrites top-level {$contains: s} to
  {content: {$contains: s}} before translation; _extract_keyword_text
  still reads the original dict first so keyword_text is preserved.

- MED (adv): dikw_stage silently dropped on INSERT — listed in
  _COLUMN_META_KEYS but missing from the INSERT column list. Fix: added
  dikw_stage between source_id and entity in both base INSERT and
  ON CONFLICT DO UPDATE SET.

- MED (adv): _connect leaked a Postgres connection when register_vector
  raised (e.g. vector extension missing). Fix: try/except closes conn
  on any BaseException before re-raising.

- LOW (adv + CodeRabbit MemPalace#173): $and + $or at the same node level, or a
  logical op mixed with field keys, silently dropped one branch. Fix:
  _translate_where.emit rejects both ambiguous shapes up front with
  UnsupportedFilterError.

- LOW (adv): n_results unvalidated. Fix: positive-int guard at top of
  query() raising ValueError.

- MINOR (CodeRabbit MemPalace#54): RECENCY_HALF_LIFE_SECONDS was a misnomer —
  EXP(-Δt/T) is a 1/e time constant, not a half-life. Fix: renamed
  constant to RECENCY_DECAY_SECONDS and updated the one SQL reference;
  comment clarifies the formula shape. Behaviour unchanged.

- MINOR (CodeRabbit MemPalace#124): $contains ILIKE pattern f'%{arg}%' leaked %
  and _ wildcards from user input (e.g. 'foo_bar' or '50%' acted as
  wildcards). Fix: _escape_like helper escapes |, %, _ with | as the
  escape char, paired with ESCAPE '|' in the SQL. Substring-only
  semantics restored.

Simplify R1 2 LOW cosmetic findings remain accepted-non-blocking per
R1 justification (see code_review round_results).

File now 686 LOC (624 → 686, +62 for the 7 fixes). Under 750 cap.

Refs: specs/IMPL-AO-S301-T03-BACKENDS-NEXUS-001.yaml v0.2.0,
SPEC-KIRA-MEMPALACE-ADOPTION-001, SPEC-AGENT-BOOT-WAKE-UP-001.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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