floci-io/floci · error · AwsException

ValidationException

ValidationException

Error message

Export is required.

What it means

Thrown by Floci's BCM Data Exports emulator when the Export object in the request body is missing, not a JSON object, or empty (parseExport rejects null/non-object/empty nodes with ValidationException 400). This typically guards UpdateExport-style calls where the whole Export payload must be present.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/bcmdataexports/BcmDataExportsJsonHandler.java:143

        for (ExportExecution exec : executions) {
            arr.add(serializeExecution(exec));
        }
        return Response.ok(response).build();
    }

    private Response handleGetExecution(JsonNode request) {
        String arn = stringOrNull(request, "ExportArn");
        String executionId = stringOrNull(request, "ExecutionId");
        ExportExecution exec = service.getExecution(arn, executionId);
        ObjectNode response = objectMapper.createObjectNode();
        response.put("ExportArn", arn);
        response.set("Execution", serializeExecution(exec));
        return Response.ok(response).build();
    }

    private Export parseExport(JsonNode node) {
        if (node == null || !node.isObject() || node.isEmpty()) {
            throw new AwsException("ValidationException", "Export is required.", 400);
        }
        Export e = new Export();
        e.setName(stringOrNull(node, "Name"));
        e.setDescription(stringOrNull(node, "Description"));
        e.setDataQuery(parseDataQuery(node.path("DataQuery")));
        e.setDestinationConfigurations(parseDestination(node.path("DestinationConfigurations")));
        e.setRefreshCadence(parseRefreshCadence(node.path("RefreshCadence")));
        return e;
    }

    private DataQuery parseDataQuery(JsonNode node) {
        if (!node.isObject() || node.isEmpty()) {
            return null;
        }
        DataQuery dq = new DataQuery();
        dq.setQueryStatement(stringOrNull(node, "QueryStatement"));
        JsonNode tableConfigs = node.path("TableConfigurations");
        if (tableConfigs.isObject()) {

View on GitHub (pinned to 62ff490619)

Solutions

  1. Include a fully populated Export object (Name, DataQuery, DestinationConfigurations, RefreshCadence) in the request.
  2. If using the AWS SDK, build the export via Export.builder() and set it on the request before send.
  3. Validate the payload is a non-empty JSON object before sending when calling the endpoint over raw HTTP.
  4. Check for accidental serialization of an empty Export (e.g. Jackson serializing an unset field as {}).

Example fix

// before
String body = "{\"Export\": {}}";

// after
String body = "{\"Export\": {\"Name\":\"cost-export\",\"DataQuery\":{\"QueryStatement\":\"SELECT ...\",\"TableConfigurations\":{}},\"DestinationConfigurations\":{\"S3Destination\":{\"S3Bucket\":\"my-bucket\",\"S3Region\":\"us-east-1\",\"S3OutputConfigurations\":{}}},\"RefreshCadence\":{\"Frequency\":\"SYNCHRONOUS\"}}}";
Defensive patterns

Strategy: validation

Validate before calling

JsonNode export = request.path("Export");
if (export == null || !export.isObject() || export.isEmpty()) {
    throw new IllegalArgumentException("Export must be a non-empty object");
}
// safe to dispatch

Type guard

private static boolean isValidExportNode(JsonNode n) {
    return n != null && n.isObject() && !n.isEmpty() && n.hasNonNull("Name");
}

Prevention

When it happens

Trigger: Calling the BCM Data Exports JSON endpoint (e.g. UpdateExport) with a body that omits the Export member, sends "Export": {}, sends a scalar/array instead of an object, or sends an empty JSON document.

Common situations: SDK request built with an unset Export builder; hand-rolled HTTP requests with malformed JSON; serializing an empty Export object; copying a GetExport response shape but stripping fields.

Related errors


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