Files
ob-elixir/tasks/11-fix-error-display-in-buffer.md
2026-01-25 00:06:56 +01:00

5.1 KiB

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):

(list (ob-elixir--format-error error-info)))

Proposed change:

(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.

(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.

(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:

#+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.