← Back to Docs

DIALYZER FIX PLAN

Documentation for DIALYZER_FIX_PLAN from the Dspex repository.

Dialyzer Fix Plan - 72 Errors Analysis & Solutions

Root Cause Analysis Summary

The Dialyzer report reveals 72 type errors across the V2 Pool implementation. These errors fall into 7 main categories:

Error Categories by Severity

  1. Pattern Match Errors (8 errors) - HIGH PRIORITY

    • Impossible pattern matches due to type misalignment
    • Primary cause: Error handling return types changed but patterns not updated
  2. Contract Supertype Errors (16 errors) - MEDIUM PRIORITY

    • Type specs too broad compared to actual function behavior
    • Primary cause: Generic map() specs vs specific struct types
  3. Unmatched Return Errors (13 errors) - MEDIUM PRIORITY

    • Function return values not captured/handled
    • Primary cause: Missing error handling for side-effect functions
  4. Guard Fail Errors (7 errors) - MEDIUM PRIORITY

    • Impossible guard conditions
    • Primary cause: Guards checking for nil when values can’t be nil
  5. Missing Range Errors (4 errors) - LOW PRIORITY

    • Function specs missing return types
    • Primary cause: Functions returning float() but specs only allow integer()
  6. Extra Range Errors (3 errors) - LOW PRIORITY

    • Function specs have unreachable types
    • Primary cause: Defensive specs for edge cases that don’t occur
  7. Pattern Match Coverage Errors (3 errors) - LOW PRIORITY

    • Unreachable pattern clauses
    • Primary cause: Catch-all patterns after complete type coverage

Detailed Fix Strategy by File

1. lib/dspex/adapters/python_pool_v2.ex (5 errors)

Root Cause: Error handling was redesigned to return PoolErrorHandler structs, but error pattern matching still expects old tuple formats.

Errors:

  • Lines 406, 410, 414, 418, 422: Pattern matches for {:pool_timeout, _}, {:checkout_failed, _}, etc. expect tuples but receive %PoolErrorHandler{} structs

Fix Strategy:

# Before:
{:pool_timeout, _reason} -> 
{:checkout_failed, _reason} ->

# After: 
%PoolErrorHandler{error_category: :timeout_error} ->
%PoolErrorHandler{error_category: :resource_error} ->

2. lib/dspex/python_bridge/error_recovery_orchestrator.ex (10 errors)

Root Cause: Function specs use generic map() but functions actually work with specific PoolErrorHandler structs.

Errors:

  • Lines 335, 468, 487, 573, 583, 592: Contract supertype errors
  • Lines 287: Unmatched return from Task.yield
  • Lines 470, 494, 585, 603: Impossible guard clauses checking map() === nil
  • Line 490: Pattern match for nil when type is specific module

Fix Strategy:

# Before:
@spec execute_retry_recovery(map(), recovery_strategy()) :: {:ok, term()} | {:error, term()}

# After:
@spec execute_retry_recovery(PoolErrorHandler.t(), recovery_strategy()) :: {:ok, term()} | {:error, term()}

# Remove impossible guards:
# Before: when fallback_adapter === nil
# After: when is_nil(fallback_adapter) (only if fallback_adapter can actually be nil)

3. lib/dspex/python_bridge/circuit_breaker.ex (2 errors)

Root Cause: Type specs don’t precisely match function behavior.

Errors:

  • Line 405: handle_failure/2 spec allows generic term() but function specifically handles failure details
  • Line 457: time_until_retry/1 returns float() but spec only allows non_neg_integer()

Fix Strategy:

# Before:
@spec time_until_retry(circuit()) :: non_neg_integer()

# After:
@spec time_until_retry(circuit()) :: non_neg_integer() | float()

4. lib/dspex/python_bridge/pool_error_handler.ex (4 errors)

Root Cause: Type specs include defensive types that are never actually returned.

Errors:

  • Line 89: Generic map() spec vs specific PoolErrorHandler struct
  • Lines 254, 279: Extra :warning and :minor severity types never returned
  • Line 267: Unreachable catch-all pattern

Fix Strategy:

# Before:
@spec wrap_pool_error(term(), map()) :: map()

# After:
@spec wrap_pool_error(term(), map()) :: PoolErrorHandler.t()

# Remove unreachable patterns and tighten specs

5. lib/dspex/python_bridge/session_pool_v2.ex (12 errors)

Root Cause: ETS operations and error handling return values not captured.

Errors:

  • Lines 226, 862: Impossible guards
  • Line 289: Missing return types in specs
  • Lines 319, 327: Contract supertype issues
  • Lines 422, 439, 461, 470, 512, 637: Unmatched ETS operation returns
  • Lines 683, 684: Unmatched counter operations
  • Line 260: Unreachable pattern clause

Fix Strategy:

# Capture ETS returns:
# Before:
:ets.insert(table, data)

# After:
_result = :ets.insert(table, data)

# Fix impossible guards and tighten specs

6. lib/dspex/python_bridge/worker_metrics.ex (4 errors)

Root Cause: Pattern matching against constant true value from :telemetry.list_handlers/0.

Errors:

  • Lines 1, 305, 366: Pattern matching false when value is always true
  • Line 348: Contract supertype with generic map() spec

Fix Strategy:

# Before:
case :telemetry.list_handlers([]) do
  false -> # This never matches
  
# After: 
case :telemetry.list_handlers([]) do
  [] -> # Match empty list instead
  _handlers -> # Match actual handlers

7. Other Files (Minor Issues)

lib/dspex.ex (1 error): Unmatched return from validation function
lib/dspex/python_bridge/error_reporter.ex (6 errors): Unmatched returns and contract supertypes
lib/dspex/python_bridge/retry_logic.ex (2 errors): Contract supertype and missing float return
lib/dspex/python_bridge/session_affinity.ex (2 errors): Contract supertype and unmatched ETS return
lib/dspex/python_bridge/worker_recovery.ex (2 errors): Extra/missing range in return types

Implementation Priority & Timeline

Phase 1: Critical Fixes (Day 1)

  1. Pattern Match Errors - Fix python_pool_v2.ex error handling patterns
  2. Core Contract Issues - Fix main error recovery orchestrator contracts

Phase 2: Contract Refinement (Day 2)

  1. Replace generic map() with specific struct types across all modules
  2. Fix impossible guard clauses by removing or correcting logic
  3. Add missing return value handling for side-effect functions

Phase 3: Cleanup (Day 3)

  1. Fix missing/extra range issues in type specifications
  2. Remove unreachable patterns and dead code
  3. Final Dialyzer validation

Testing Strategy

  1. Run Dialyzer after each phase to verify error reduction
  2. Run existing test suite to ensure no regressions
  3. Focus on error handling tests to verify pattern matching fixes

Risk Assessment

  • LOW RISK: Most errors are type specification mismatches, not logic errors
  • MEDIUM RISK: Pattern matching fixes require careful testing of error paths
  • HIGH CONFIDENCE: V2 Pool functionality remains intact, only improving type safety

Expected Outcome

  • From 72 errors to 0 errors
  • Improved type safety across V2 Pool implementation
  • Better IDE support with accurate type information
  • Maintained backward compatibility and functionality