Skip to content

Stop leaking raw exception messages to API clients #26

Description

@devops-thiago

Background

GlobalExceptionHandler (src/main/java/br/com/arquivolivre/myjavagenie/controller/GlobalExceptionHandler.java) returns ex.getMessage() verbatim to clients for IllegalArgumentException, ModelTimeoutException, ModelInvocationException, ModelInitializationException, and the generic handler. These messages are built from provider/exception internals, e.g. "Language model generation failed: " + e.getMessage() in QueryService.generateWithTimeout, which can embed upstream API error details.

Impact

  • Internal details (base URLs, request fragments, provider error payloads, filesystem paths) can leak to API consumers and the chat UI.
  • Error handling is inconsistent: some paths sanitize via LogSanitizer, but the client-facing body does not.
  • The chat UI surfaces these messages directly in the error banner, so a user can see provider internals.

How to reproduce

  1. Point model.self-hosted.base-url at a closed port (or use an invalid API key).
  2. Ask a question via POST /api/chat/query.
  3. Observe the response body contains the raw connection/authentication error message from the provider instead of a generic message.

Where the fix should land

In GlobalExceptionHandler, map each exception type to a stable, user-facing message while keeping the current HTTP statuses:

  • Timeout → "The request timed out while generating the answer. Please try again."
  • Invocation/initialization → "The language model is temporarily unavailable. Please try again later."
  • Generic → "An unexpected error occurred."

Keep full detail in the logs (the handlers already log with the exception object).

Files touched

  • src/main/java/br/com/arquivolivre/myjavagenie/controller/GlobalExceptionHandler.java
  • Tests under src/test/java/... (new GlobalExceptionHandlerTest or updates to existing controller tests)

Acceptance criteria

  • Client error bodies contain no raw exception text or provider internals.
  • Logs still contain the full stack trace and cause.
  • HTTP status codes unchanged (400/504/503/500).
  • Tests assert generic messages and preserved statuses; mvn test and mvn spotless:check pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingjavaPull requests that update java code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions