Skip to content

elixir-devex: Use structured WasmError exceptions in all core error paths#8

Open
yevbar wants to merge 4 commits intomasterfrom
grumpy/structured-wasm-errors
Open

elixir-devex: Use structured WasmError exceptions in all core error paths#8
yevbar wants to merge 4 commits intomasterfrom
grumpy/structured-wasm-errors

Conversation

@yevbar
Copy link
Copy Markdown
Contributor

@yevbar yevbar commented Feb 28, 2026

By Grumpy

What

Replace bare RuntimeError raises with structured Firebird.WasmError exceptions across all core API error paths (load!, call!, call_one!, run!, run_one!, pipe!, map, quick).

Why

Before this change, errors from Firebird raised generic RuntimeError with string messages. Developers couldn't:

  • Pattern match on error types (rescue e in Firebird.WasmError)
  • Programmatically inspect error fields (e.reason, e.function, e.wasm_path)
  • Get consistent, actionable fix suggestions across all error paths

Changes

New WasmError constructors:

  • instance_stopped/1 — clear message when calling on a dead instance with reload instructions
  • call_failed/3 — context-aware hints (detects timeout, arity mismatch, exit reasons)

Updated error paths (3 lib files):

  • Firebird.load!/2: raises WasmError.file_not_found or WasmError.load_failed
  • Firebird.call!/3, call_one!/3: raises WasmError.function_not_found (with 'Did you mean?' via Jaro distance), WasmError.instance_stopped, or WasmError.call_failed
  • Firebird.run!/4, run_one!/4: propagates structured errors
  • Firebird.Runtime.call!/4: same structured error pattern

Updated 12 test files to expect WasmError instead of RuntimeError, plus comprehensive new test coverage in dx_error_quality_test.exs.

HDR Agent and others added 4 commits February 28, 2026 21:01
Previously, `use Firebird.TestCase, wasm: Path.join([__DIR__, ...])`
crashed with a cryptic CaseClauseError because the macro only handled
string literals, :sample, and false.

Now any expression that evaluates to a string at runtime is accepted:
  - Path.join([__DIR__, ...])
  - Path.expand(...)
  - Module attributes (@wasm_path)
  - Any other expression returning a string

If the expression evaluates to a non-string, a clear ArgumentError is
raised: 'must resolve to a string path, got: ...'

Added tests for: Path.join, Path.expand, module attributes, string
literals (regression), and error message format.
Replace bare RuntimeError raises with Firebird.WasmError in:
- Firebird.load!/2: file not found, load failures
- Firebird.call!/3, call_one!/3: function not found (with 'Did you mean?'),
  instance stopped, call failures
- Firebird.run!/4, run_one!/4: propagate structured errors
- Firebird.Runtime.call!/4: same improvements

Add new WasmError constructors:
- instance_stopped/1: clear message when calling on dead instance
- call_failed/3: context-aware hints (timeout, arity mismatch, etc.)

Benefits:
- All errors are rescuable with 'rescue e in Firebird.WasmError'
- Structured fields (reason, function, wasm_path) for programmatic handling
- Every error includes actionable fix suggestions
- 'Did you mean?' suggestions via Jaro distance on function names

Update 12 test files to expect WasmError instead of RuntimeError.
Add comprehensive test coverage in dx_error_quality_test.exs.
- Run mix format on entire project
- Fix unused generate_expr/3 in wat_gen.ex
- Fix unused module_name variable in firebird.compile.ex
- Register @wasm attribute in wasm_modules to suppress warnings
- Silence FastNif load warning (expected in most environments)
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.

1 participant