Prompt
Error handling should be designed to provide clear, actionable information to developers while avoiding redundancy. Follow these practices:
- Don’t duplicate error reporting - If you’re throwing an exception, don’t also log the same error. This creates noise and confusion.
// BAD:
log.errorf("Error unzipping import file %s: %s", fileName, e.getMessage());
throw new IllegalStateException(String.format("Error unzipping import file %s: %s",
fileName, e.getMessage()), e);
// GOOD:
throw new IllegalStateException(String.format("Error unzipping import file %s: %s",
fileName, e.getMessage()), e);
- Provide actionable error messages - Include information about what went wrong and how to fix it.
// VAGUE:
throw new DeploymentException(String.format("Class %s has no fields.", className));
// BETTER:
throw new DeploymentException(String.format("Class %s has no fields. Parameters containers are only supported if they have at least one annotated field.", className));
- Handle unsupported operations gracefully - When a feature might not be supported by all implementations, use try-catch with informative messages:
try {
options.setUseAlpn(sslOptions.isUseAlpn());
} catch (UnsupportedOperationException e) {
log.warn("ALPN configuration not supported by implementation: %s. ALPN setting will be ignored."
.formatted(options.getClass().getName()));
}
- Use exceptions for misconfigurations - Log warnings for non-critical issues, but throw exceptions for misconfigurations that would lead to incorrect behavior:
// NOT IDEAL:
if (hasBasic && hasApiKey) {
LOG.warn("Multiple authentication methods configured. Defaulting to Basic Authentication.");
return EsAuth.BASIC;
}
// BETTER:
if (hasBasic && hasApiKey) {
throw new IllegalArgumentException("Multiple authentication methods configured. Please specify only one authentication method.");
}
- Design interfaces to prevent errors - Use language features like abstract methods when you expect implementations to provide functionality, rather than runtime exceptions.