Skip to main content

On This Page

Standardizing Error Translation to Prevent Abstraction Leakage in Go

2 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

Fixing Abstraction Leakage: Standardizing Error Handling Across Layered Services

Viktor Logvinov identifies abstraction leakage as a silent saboteur that occurs when infrastructure errors propagate directly to protocol layers without translation. A raw database error like “sql: no rows in result set” surfacing in a gRPC response is a clear breach of trust between system layers.

Why This Matters

In microservices architectures, abstraction leakage erodes encapsulation and exposes internal implementation details, such as database schemas or driver behaviors, to external clients. Without standardized translation, error handling becomes inconsistent across endpoints, leading to lost debugging context and potential cascading failures where system timeouts are misinterpreted by clients as logical application errors.

Key Insights

  • The Layered Translation Strategy transforms errors across three stages: Infrastructure to Domain, then Domain to Protocol (e.g., SQL error to ‘resource_not_found’ to HTTP 404).
  • Selective wrapping preserves original errors for internal logging via Go’s errors.Wrap while exposing only domain-relevant details to clients.
  • Error response versioning, such as ‘V1_RESOURCE_NOT_FOUND’, provides a graceful migration path and prevents breaking existing clients during schema updates.
  • Unwrapped infrastructure errors like ‘deadline exceeded’ are often indistinguishable from network timeouts, leading to incorrect client retry logic.
  • Effective error translation acts as a prerequisite for building scalable systems, preventing a single database error from undermining service resilience and observability.

Working Examples

Example of intercepting and wrapping an infrastructure error within the domain layer.

err := errors.Wrap(infraErr, "resource not found in database")

Structured logging pattern to preserve infrastructure context while tracking translated domain errors.

log.WithError(originalErr).WithField("domain_error", translatedErr).Error("Resource not found")

Practical Applications

  • Use Case: A database ‘unique constraint violation’ is translated to a domain ‘resource_conflict’ and returned as an HTTP 409 Conflict. Pitfall: Returning raw SQL errors exposes database schema details and forces clients to implement brittle, case-specific logic.
  • Use Case: Versioning error codes like ‘V2_RESOURCE_NOT_FOUND’ allows for rolling out new error taxonomy via feature flags. Pitfall: Immediate changes to error formats without versioning can break legacy client integrations and compromise service reliability.
  • Use Case: Mapping a database pool ‘deadline exceeded’ to a domain ‘service_unavailable’. Pitfall: Masking critical errors with generic ‘internal server error’ messages hides root causes like full disks or connection pool exhaustion.

References:

Continue reading

Next article

GamePinned: NTFS-Level Protection Against Game Uninstalls on Shared Windows PCs

Related Content