~/wiki

interface inconsistency

---
title: Interface Inconsistency
category: concepts
created: 2025-12-21
updated: 2025-01-04
tags: [interface-inconsistency, data-structure-mismatch, rag-architecture, chunk-objects, polymorphism, type-safety, production-failures, tf-idf-retrieval, bm25-retrieval, postgres-retrieval, build-prompt-failures, logging-failures, category-5-bugs, architectural-patterns, abstraction-violations, retriever-interface, return-type-mismatch, embedder-initialization, runtime-crashes, assistant-rh-bugs, abrupt-analysis-termination, tuples-vs-objects, downstream-consumer-failures, maintenance-complexity]
sources: [raw/conversations/2025-10-23-codex-assistant-rh-c34c0439.md]
confidence: high
---

# Interface Inconsistency

Architectural anti-pattern where components implementing the same interface return incompatible data structures, breaking polymorphic usage and causing downstream system failures. Particularly problematic in RAG systems where retriever implementations must provide uniform interfaces for prompt building and result processing.

## The Problem

When multiple implementations of the same interface return different data types, it violates the Liskov Substitution Principle and breaks code that depends on consistent behavior. This leads to:

- **Runtime Type Errors**: Downstream code crashes when expecting objects but receiving tuples
- **Silent Failures**: Systems may partially work but fail in specific code paths
- **Maintenance Complexity**: Every consumer must handle multiple data formats
- **Testing Gaps**: Interface violations often escape unit tests focused on individual components

## Case Study: Assistant-RH RAG System

In the assistant-rh system, a critical interface inconsistency was identified:

### The Inconsistency
- **TF-IDF Retriever**: Returns `(index, score)` tuples
- **BM25 Retriever**: Returns `(index, score)` tuples  
- **Postgres Retriever**: Returns `Chunk` objects
- **Expected Interface**: All should return `Chunk` objects

### Downstream Failures
```python
# This works with Postgres retriever
chunks = retriever.search(query)
prompt = build_prompt(chunks)  # Expects Chunk objects with .text attribute

# This crashes with TF-IDF/BM25 retrievers
chunks = retriever.search(query)  # Returns [(index, score), ...]
prompt = build_prompt(chunks)     # AttributeError: tuple has no attribute 'text'

Impact

  • Logging Systems: Crash when trying to log chunk metadata
  • Prompt Building: Fails when extracting text from tuples
  • Result Processing: Breaks any code expecting consistent chunk objects
  • Testing: Creates "Category 5" bugs that cause complete system crashes

Prevention Strategies

1. Strong Typing

from typing import Protocol, List

class Chunk:
    text: str
    score: float
    metadata: dict

class Retriever(Protocol):
    def search(self, query: str) -> List[Chunk]:
        ...

2. Interface Testing

def test_retriever_interface_consistency():
    """Test all retrievers return compatible objects."""
    retrievers = [TFIDFRetriever(), BM25Retriever(), PostgresRetriever()]
    
    for retriever in retrievers:
        results = retriever.search("test query")
        assert all(hasattr(chunk, 'text') for chunk in results)
        assert all(hasattr(chunk, 'score') for chunk in results)

3. Abstract Base Classes

from abc import ABC, abstractmethod

class BaseRetriever(ABC):
    @abstractmethod
    def search(self, query: str) -> List[Chunk]:
        """Must return List[Chunk], not tuples or other formats."""
        pass

4. Adapter Pattern

When interface changes are necessary:

class LegacyRetrieverAdapter(BaseRetriever):
    def __init__(self, legacy_retriever):
        self.legacy = legacy_retriever
    
    def search(self, query: str) -> List[Chunk]:
        tuples = self.legacy.search(query)
        return [Chunk(text=get_text(idx), score=score) 
                for idx, score in tuples]

Detection

Interface inconsistencies often manifest as:

  • AttributeError: Object has no attribute 'expected_field'
  • TypeError: Expected X, got Y
  • Silent Failures: Code continues but produces wrong results
  • Test Inconsistencies: Tests pass individually but fail in integration

Resolution

  1. Identify All Implementations: Find every class implementing the interface
  2. Document Expected Contract: Clearly specify return types and behavior
  3. Create Compliance Tests: Test the interface contract, not implementation details
  4. Refactor Gradually: Use adapter pattern for gradual migration
  5. Enforce at Type Level: Use type hints and static analysis tools

Interface consistency is fundamental to maintainable software architecture. In RAG systems, where different retrieval strategies must be interchangeable, maintaining uniform interfaces is critical for system reliability and extensibility.

See also