Standardizing Error Translation to Prevent Abstraction Leakage in Go
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
Web Security Fundamentals for Engineers: 2026 Implementation Guide
Implement the 20% of security practices that prevent 80% of common web attacks through rigorous input validation and session management.
Code as Data: Why LLMs Fail at Structural Programming Tasks
George Ciobanu introduces pandō, a structural engine designed to stop AI agents from treating codebases as unstructured text to prevent broken production builds.
Trunk-Based Development: Decoupling Deployment from Release for True CI/CD
Learn how to implement true continuous integration by eliminating long-lived feature branches and decoupling deployments from releases.