floci-io/floci · error · AwsException

InternalError

InternalError

Error message

e.getMessage() != null ? e.getMessage() : "Service invocation failed"

What it means

InternalError (HTTP 500) is the catch-all rethrown by ApiGatewayService's AWS integration router when a routed service handler throws anything that is not itself an AwsException. The original exception's message is preserved when present ('e.getMessage()' is non-null), otherwise the generic text 'Service invocation failed' is used. It signals a defect or unexpected condition inside the emulator's service dispatch, not a malformed client request.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/apigateway/AwsServiceRouter.java:175

                case "dynamodb" -> dynamoDbHandler.handle(action, requestBody, region);
                case "sqs" -> sqsHandler.handle(action, requestBody, region);
                case "sns" -> snsHandler.handle(action, requestBody, region);
                case "events" -> eventBridgeHandler.handle(action, requestBody, region);
                case "ssm" -> ssmHandler.handle(action, requestBody, region);
                case "kinesis" -> kinesisHandler.handle(action, requestBody, region);
                case "logs" -> logsHandler.handle(action, requestBody, region);
                case "monitoring" -> metricsHandler.handle(action, requestBody, region);
                case "secretsmanager" -> secretsManagerHandler.handle(action, requestBody, region);
                case "kms" -> kmsHandler.handle(action, requestBody, region);
                case "cognito-idp" -> cognitoHandler.handle(action, requestBody, region);
                case "acm" -> acmHandler.handle(action, requestBody, region);
                default -> throw new AwsException("UnknownService",
                        "Unsupported AWS service integration: " + service, 400);
            };
        } catch (AwsException e) {
            throw e;
        } catch (Exception e) {
            throw new AwsException("InternalError",
                    e.getMessage() != null ? e.getMessage() : "Service invocation failed", 500);
        }
    }

    /**
     * Dispatches an AWS query-protocol (form-encoded) integration request.
     *
     * <p>Used for {@code path/}-style integration URIs whose VTL request template renders an
     * {@code application/x-www-form-urlencoded} body in the AWS query protocol, e.g.
     * {@code Action=SendMessage&QueueUrl=...&MessageBody=...}. The {@code Action} parameter
     * selects the operation, mirroring {@link io.github.hectorvent.floci.core.common.AwsQueryController}.
     *
     * @param service the AWS service name from the URI (e.g., "sqs")
     * @param params  the parsed form parameters, including {@code Action}
     * @param region  the AWS region
     * @return the service response (query-protocol XML)
     */
    public Response invokeQuery(String service, MultivaluedMap<String, String> params, String region) {

View on GitHub (pinned to 62ff490619)

Solutions

  1. Inspect the Floci server logs for the stack trace of the wrapped exception — the InternalError message is just the original exception's getMessage(), which is often the real clue.
  2. Capture the rendered integration request (enable API Gateway execution logging / test-invoke) and replay the same action directly against the target service to isolate whether the payload is the problem.
  3. Simplify the VTL template to a minimal known-good body and re-add transformations incrementally until the failure reappears.
  4. If the payload is valid, report the exception message plus the service/action pair as a Floci bug.
Defensive patterns

Strategy: try-catch

Try / catch

catch (AwsException e) {
    if ("InternalError".equals(e.getCode())) {
        // emulator-side fault: capture the message (it carries the cause's text) and report,
        // never retry blindly — the same template will fail identically
        log.error("Integration dispatch failed: {}", e.getMessage());
        throw new IntegrationExecutionException("Check Floci logs for the wrapped stack trace", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An integration request is routed to a supported handler (sqs, sns, dynamodb, ...) and that handler throws a RuntimeException — e.g. a JSON parse error on the VTL-rendered body, a ClassCastException on a response field, or an NPE on a missing parameter the handler did not validate. The switch in invokeJson() succeeds; the failure happens inside handle().

Common situations: VTL request templates that render malformed JSON for the target service action, causing downstream parse exceptions. Emulator edge cases such as a target resource deleted concurrently between route and handle. Version mismatches after upgrading Floci where a handler signature changed.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/b381edb06824f369. Report an issue: GitHub.