Skip to content

fix(ui): erros de parametro do detector voltam a chegar ao usuario - #465

Merged
MarkSant merged 1 commit into
mainfrom
fix/detector-parameter-error-boundary
Aug 15, 2026
Merged

fix(ui): erros de parametro do detector voltam a chegar ao usuario#465
MarkSant merged 1 commit into
mainfrom
fix/detector-parameter-error-boundary

Conversation

@MarkSant

Copy link
Copy Markdown
Owner

O bug

Clicar "Aplicar" no painel do detector com um valor fora da faixa não fazia nada: sem diálogo, sem linha de status. O painel capturava o ValidationError do pydantic; o DetectorSetupCoordinator levantava DetectorSetupCoordinatorError, na época subclasse de Exception pura. Tipos sem parentesco — o except nunca casava, e nada mais capturava.

Um censo de coordinators/ achou 31 pontos de raise e zero handlers em src/. Todos escapavam para o report_callback_exception padrão do Tk, que escreve num stderr que o app empacotado não tem.

A correção

Uma hierarquia. CoordinatorError passa a herdar de ZebTrackError, e DetectorSetupCoordinatorError de CoordinatorError — era o único erro de coordinator ainda derivando direto de Exception. except ZebTrackError numa fronteira de UI agora pega qualquer falha da aplicação.

Um ValidationError. zebtrack/exceptions.py redefinia a hierarquia inteira que zebtrack/core/exceptions.py já declarava — inclusive uma segunda classe ValidationError, usada por ninguém. Duas classes de mesmo nome fazem o except de uma ignorar a outra em silêncio: o mesmo bug em miniatura. O módulo virou shim de reexportação; core/exceptions.py é o canônico.

Duas naturezas de falha, dois tipos — é a parte a preservar ao adicionar fronteiras em outros lugares:

Falha Tipo Mensagem é para UI mostra
Usuário digitou valor fora da faixa ValidationError o pesquisador str(exc) literal — por isso agora com _() e par pt_BR
Serviço levantou, plugin não carregou DetectorSetupCoordinatorError o log mensagem genérica; o detalhe vai para o structlog

Três call sites, três fronteiras: model_diagnostics_panel, event_dispatcher (assinante de DETECTOR_UPDATE_PARAMETERS, responde com UI_SHOW_ERROR) e gui.py.

Rede de segurança: ui/tk_exception_handler substitui o report_callback_exception do Tk por um handler que registra ui.callback.unhandled via structlog e mostra diálogo. Instalado em app_runner.run_app() logo após a criação da raiz. É rede, não fronteira: cada ocorrência no log é um relatório de bug contra um call site.

Handler que não pode disparar é pior que handler nenhum. UIStateController.update_detector_parameters embrulhava o coordinator em except ValueErrorUI_SHOW_ERROR; nada em src/ o chamava, e o coordinator já consumia o ValueError antes. Inalcançável em dobro, e ainda fazia o fluxo parecer coberto num grep. Removido em vez de consertado.

Fora de escopo, ainda aberto

track_buffer tem três faixas discordantes: settings.py (ge=10, le=1000), DetectorSetupCoordinator (>= 0), DetectorService (>= 1). Reconfirmei que continuam divergentes após #463 — aquele PR corrigiu só o tipo do erro, não as faixas. Escolher uma é decisão de domínio; os limites ficaram intactos.

Verificação

  • ruff check + ruff format --check — limpos
  • mypy . — limpo (702 arquivos)
  • pytest -q — 4222 passed, 5 skipped (+20 novos)
  • pytest -m gui -n0 -q — 1087 passed, 1 skipped (+8 novos)
  • Catálogos: as 5 strings novas estão no .po e o .mo está compilado — verificado resolvendo cada uma via gettext em runtime
  • Documentado em docs/reference/system_integration.md §5.13

🤖 Generated with Claude Code

Clicking "Apply" in the detector panel with an out-of-range value did
nothing at all: no dialog, no status line. The panel caught pydantic's
ValidationError, while DetectorSetupCoordinator raised
DetectorSetupCoordinatorError — at the time a bare Exception subclass.
Unrelated types, so the except never matched, and nothing else caught it
either. A census of coordinators/ found 31 raise sites and zero handlers
in src/; all of them escaped into Tk's default report_callback_exception,
which writes a traceback to a stderr the packaged app does not have.

One hierarchy. CoordinatorError now derives from ZebTrackError and
DetectorSetupCoordinatorError from CoordinatorError, so `except
ZebTrackError` at a UI boundary catches any application failure.

One ValidationError. zebtrack/exceptions.py redefined the entire
hierarchy that zebtrack/core/exceptions.py already declared, including a
second ValidationError used by nobody. Two same-named classes make
`except` on one silently miss the other — the same bug in miniature. The
module is now a re-export shim; core/exceptions.py is canonical.

Two kinds of failure, two types. A value out of range raises
ValidationError, whose message is written for the researcher and rendered
verbatim (hence `_()` and a pt_BR pair). Anything else keeps
DetectorSetupCoordinatorError, whose message names services and plugins
and belongs in the log, answered by a generic dialog. Collapsing the two
is what left the panel unable to answer either.

The three call sites of hardware_vm.update_detector_parameters
(model_diagnostics_panel, event_dispatcher, gui.py) carry the same
two-clause boundary.

ui/tk_exception_handler installs a replacement for Tk's
report_callback_exception that logs ui.callback.unhandled via structlog
and shows a dialog, wired in app_runner.run_app() right after the root
window exists. It is a net, not a boundary: every entry it logs is a bug
report against a call site.

UIStateController.update_detector_parameters is deleted rather than
repaired — nothing in src/ called it, and the coordinator consumed the
ValueError before its `except ValueError` could fire. Unreachable twice
over, while making the flow look covered in a grep.
project_model_configuration_panel had a milder version of the same and
now catches ZebTrackError.

Out of scope, still open: track_buffer has three disagreeing bounds
(settings.py ge=10 le=1000, coordinator >= 0, service >= 1). Picking one
is a domain decision; the bounds are untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 15, 2026 14:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a UI regression where invalid detector parameter values (e.g., out-of-range thresholds) could fail silently by ensuring all coordinator failures participate in a single application exception hierarchy and by adding explicit UI “error boundaries” (plus a Tk callback safety net) so errors reliably reach the user and/or logs.

Changes:

  • Unifies exception handling by making CoordinatorError (and DetectorSetupCoordinatorError) derive from ZebTrackError, and making zebtrack.exceptions a pure re-export shim of zebtrack.core.exceptions.
  • Restores user-visible feedback for rejected detector parameters across the three relevant UI call sites, distinguishing user input (ValidationError) from operational failures (DetectorSetupCoordinatorError / other ZebTrackError).
  • Adds a last-resort Tk callback exception handler (logs + dialog) plus targeted tests and i18n catalog updates for the new UI-visible strings.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/ui/test_tk_exception_handler.py Tests the Tk callback safety net (logs + dialog, never re-raises).
tests/ui/test_detector_parameter_ui_boundary.py Pins down the three UI boundaries so rejected params always show a dialog and never escape to Tk.
tests/test_detector_parameter_error_boundary.py Verifies exception hierarchy unification and the ValidationError vs operational-failure split at the coordinator boundary.
src/zebtrack/ui/tk_exception_handler.py Implements the Tk report_callback_exception replacement safety net.
src/zebtrack/ui/gui.py Adds a boundary to the legacy _on_apply_roi_settings stub so it can’t fail silently.
src/zebtrack/ui/components/project_model_configuration_panel.py Fixes an unreachable handler by catching ZebTrackError (not pydantic’s ValidationError) and logging failures.
src/zebtrack/ui/components/model_diagnostics_panel.py Adds the two-clause boundary (ValidationError vs other ZebTrackError) for the Apply button flow.
src/zebtrack/ui/components/event_dispatcher.py Adds the same boundary inside the DETECTOR_UPDATE_PARAMETERS subscriber, routing failures to UI_SHOW_ERROR.
src/zebtrack/locales/zebtrack.pot Updates msgids/source references for the new UI-visible strings.
src/zebtrack/locales/pt_BR/LC_MESSAGES/zebtrack.po Adds pt_BR translations for the new UI-visible strings.
src/zebtrack/locales/_pairs/pr4-error-boundary.json Adds translation pairs for the new boundary/net strings.
src/zebtrack/exceptions.py Converts zebtrack.exceptions into a re-export shim to prevent duplicate same-named exception classes.
src/zebtrack/core/app_runner.py Installs the Tk callback exception handler immediately after root creation.
src/zebtrack/coordinators/ui_state_coordinator.py Removes the dead/unreachable update_detector_parameters boundary and documents the rationale.
src/zebtrack/coordinators/detector_setup_coordinator.py Makes coordinator errors catchable (DetectorSetupCoordinatorError derives from CoordinatorError) and raises user-facing ValidationError for rejected inputs.
src/zebtrack/coordinators/base_coordinator.py Makes CoordinatorError derive from ZebTrackError to unify catchability at UI boundaries.
docs/reference/system_integration.md Documents the error-boundary model (one hierarchy, two failure types) and the Tk safety net.
CHANGELOG.md Adds an Unreleased entry describing the bug, fix strategy, and remaining out-of-scope domain decision.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.46154% with 9 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/zebtrack/ui/components/event_dispatcher.py 80.00% 4 Missing ⚠️
...ui/components/project_model_configuration_panel.py 60.00% 2 Missing ⚠️
src/zebtrack/ui/tk_exception_handler.py 91.66% 2 Missing ⚠️
src/zebtrack/ui/gui.py 90.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@MarkSant
MarkSant merged commit 1da36b0 into main Aug 15, 2026
7 checks passed
@MarkSant
MarkSant deleted the fix/detector-parameter-error-boundary branch August 15, 2026 14:34
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