# Task 11: Fix Exception Display in Org Buffer ## Problem When an Elixir code block throws an exception, the error is not displayed in the org buffer. The error is only shown in the minibuffer/messages, leaving the user without visible feedback in their document. ### Root Cause 1. The variable `ob-elixir-signal-errors` defaults to `t` (line 57-63 in `ob-elixir.el`) 2. When an error is detected, `ob-elixir--process-result` (line 206-222) calls `signal`, which throws an Emacs error 3. The signaled error propagates up and prevents `org-babel-execute:elixir` from returning a result 4. Since no result is returned, org-babel has nothing to insert into the buffer ### Current Behavior | `ob-elixir-signal-errors` | What happens | |--------------------------|--------------| | `t` (default) | Error is signaled, shown in minibuffer, **NOT inserted in buffer** | | `nil` | Error is returned as the result string, **inserted in buffer** | ### Desired Behavior Errors should always be displayed in the org buffer as the result, regardless of the `ob-elixir-signal-errors` setting. ## Scope - Non-session execution mode only - Session mode is out of scope for this fix ## Implementation Plan ### Step 1: Modify `ob-elixir--process-result` to pass full error output **File:** `ob-elixir.el` (line 218) **Change:** When signaling an error, pass the full error output instead of the formatted short message. **Current code (line 218):** ```elisp (list (ob-elixir--format-error error-info))) ``` **Proposed change:** ```elisp (list (plist-get error-info :full-output))) ``` **Rationale:** - The `:full-output` field contains the complete multi-line error output including stack traces - This ensures the `condition-case` in `org-babel-execute:elixir` returns the same full output that would be returned when `ob-elixir-signal-errors` is `nil` - The formatted short message from `ob-elixir--format-error` only includes the exception name and first-line message, which is insufficient for debugging ### Step 2: Wrap result computation in `org-babel-execute:elixir` (ALREADY DONE) **File:** `ob-elixir.el` (lines 928-945) **Status:** This step was already implemented. The `condition-case` wraps the result computation and catches `ob-elixir-error`, returning `(cadr err)` which will now contain the full error output after Step 1 is applied. ```elisp (result (condition-case err (cond ;; Session mode with deps ((and session (not (string= session "none")) deps-string) (ob-elixir--evaluate-in-session-with-deps session full-body result-type deps-string)) ;; Session mode without deps ((and session (not (string= session "none"))) (ob-elixir--evaluate-in-session session full-body result-type)) ;; Non-session with deps (deps-string (ob-elixir--execute-with-deps full-body result-type deps-string)) ;; Plain execution (t (ob-elixir--execute full-body result-type))) (ob-elixir-error ;; Return error message so it appears in buffer (cadr err)))) ``` ### Step 3: Add tests for the new behavior **File:** `test/test-ob-elixir-errors.el` **Add new test:** Verify that errors appear in org buffer output when `ob-elixir-signal-errors` is `t`. ```elisp (ert-deftest ob-elixir-test-error-appears-in-result () "Test that errors appear in result even when signaling is enabled." (skip-unless (executable-find ob-elixir-command)) (let ((ob-elixir-signal-errors t)) ;; Execute via the main entry point (not ob-elixir--execute directly) (let ((result (org-babel-execute:elixir "raise \"test error\"" '((:result-type . value) (:result-params . ("replace")))))) ;; Result should contain the error, not be nil/empty (should result) (should (string-match-p "RuntimeError" result))))) ``` **Rationale:** The existing test `ob-elixir-test-error-signaling` tests that `ob-elixir--execute` signals an error, but doesn't test the full flow through `org-babel-execute:elixir`. The new test verifies the end-to-end behavior. ### Step 4: Update TODO.org **File:** `TODO.org` **Change:** Mark the first item ("errors should be printed in the org buffer") as DONE. ## Summary of Changes | File | Change | |------|--------| | `ob-elixir.el` | Change signal data to pass `:full-output` instead of formatted message | | `ob-elixir.el` | Wrap result computation in `condition-case` to catch `ob-elixir-error` (already done) | | `test/test-ob-elixir-errors.el` | Add test for error display in org buffer | | `TODO.org` | Mark issue as resolved | ## Files NOT Modified - Session-related code - `ob-elixir--process-result` (keeps existing signaling behavior) - `ob-elixir-signal-errors` default value (stays `t`) ## Verification After implementation, test with: ```org #+begin_src elixir raise "This error should appear in the buffer" #+end_src ``` Expected: The RuntimeError message should appear as the result block below the code block.