oscerd opened a new pull request, #25089:
URL: https://github.com/apache/camel/pull/25089

   ## Problem
   
   Every AWS producer health check catches `AwsServiceException` and records two
   details — the HTTP status code and the AWS error code. The status code is
   guarded for null; `awsErrorDetails()` is dereferenced directly:
   
   ```java
   if (ObjectHelper.isNotEmpty(e.statusCode())) {                    // guarded
       builder.detail(SERVICE_STATUS_CODE, e.statusCode());
   }
   if (ObjectHelper.isNotEmpty(e.awsErrorDetails().errorCode())) {   // 
dereferenced unguarded
       builder.detail(SERVICE_ERROR_CODE, e.awsErrorDetails().errorCode());
   }
   ```
   
   `AwsServiceException.awsErrorDetails()` is nullable — it is a builder field 
that
   defaults to null and is only populated when the SDK successfully unmarshals a
   structured error response.
   
   **This is reproduced, not theoretical.** Driving `Athena2ProducerHealthCheck`
   with a client that throws
   `AwsServiceException.builder().message("boom").statusCode(500).build()` 
fails on
   `main` with:
   
   ```
   java.lang.NullPointerException: Cannot invoke
   "software.amazon.awssdk.awscore.exception.AwsErrorDetails.errorCode()" 
because
   the return value of
   
"software.amazon.awssdk.awscore.exception.AwsServiceException.awsErrorDetails()"
 is null
   ```
   
   So instead of reporting the endpoint `DOWN` with the message it had already
   prepared, the health check propagates an NPE — a genuine "service 
unreachable"
   signal is turned into a health-check failure.
   
   The inconsistency is the tell: the author guarded `statusCode()` one line 
above.
   
   ## Fix
   
   Guarded `awsErrorDetails()` consistently with the neighbouring `statusCode()`
   check, across all **21** producer health checks (athena, comprehend, cw, ddb,
   ec2, ecs, eks, eventbridge, lambda, mq, polly, rekognition, step-functions,
   textract, timestream query + write, translate, config, parameter-store,
   secrets-manager, security-hub):
   
   ```java
   if (ObjectHelper.isNotEmpty(e.awsErrorDetails()) && 
ObjectHelper.isNotEmpty(e.awsErrorDetails().errorCode())) {
   ```
   
   `Textract2ProducerHealthCheck` additionally dereferenced it in an 
`equals(...)`
   test that classifies certain errors as healthy — two unguarded sites — so it 
now
   reads the error code once into a local:
   
   ```java
   String errorCode = e.awsErrorDetails() != null ? 
e.awsErrorDetails().errorCode() : null;
   if ("InvalidParameterException".equals(errorCode) || 
"UnsupportedDocumentException".equals(errorCode)) {
   ```
   
   ## Tests
   
   `Athena2ProducerHealthCheckErrorDetailsTest` drives the health check with a
   mocked client and covers both paths:
   
   - **null details** → `DOWN`, `service.status.code` present, 
`service.error.code`
     absent. Verified to fail on `main` with the NPE quoted above.
   - **populated details** → `DOWN` and the error code still reported, so the 
fix
     does not silently drop the detail it was meant to record.
   
   Full `camel-aws2-athena` suite: 49/49 green. Full reactor build clean.
   
   ## Backport
   
   - `camel-4.18.x` — all 21 health checks present → backport opened.
   - `camel-4.14.x` — 15 of the 21 present (parameter-store, security-hub,
     comprehend, polly, rekognition and textract do not exist on that branch) →
     backport covers those 15.
   
   ---
   _Claude Code on behalf of oscerd_


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to