{"record":{"id":"5d5653c2410de019","repo":"floci-io/floci","slug":"dataunavailableexception","errorCode":"DataUnavailableException","errorMessage":"End date must be after Start date.","messagePattern":"End date must be after Start date\\.","errorType":"error_code","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/ce/TimeBucketing.java","lineNumber":69,"sourceCode":"        try {\n            return OffsetDateTime.parse(value).toInstant();\n        } catch (DateTimeParseException ignored) {\n            // fall through\n        }\n        try {\n            return LocalDateTime.parse(value).toInstant(ZoneOffset.UTC);\n        } catch (DateTimeParseException e) {\n            throw new AwsException(\"ValidationException\",\n                    field + \" must be a YYYY-MM-DD date or ISO-8601 timestamp.\", 400);\n        }\n    }\n\n    /** A half-open [start, end) bucket aligned to the requested granularity. */\n    record Bucket(Instant start, Instant end) {}\n\n    static List<Bucket> split(Instant start, Instant end, Granularity granularity) {\n        if (!end.isAfter(start)) {\n            throw new AwsException(\"DataUnavailableException\",\n                    \"End date must be after Start date.\", 400);\n        }\n        // Truncate Start down and End up to the granularity boundary so every\n        // emitted bucket aligns to the period AWS would return.\n        Instant alignedStart = floor(start, granularity);\n        Instant alignedEnd = ceil(end, granularity);\n        return switch (granularity) {\n            case HOURLY -> splitHourly(alignedStart, alignedEnd);\n            case DAILY -> splitDaily(alignedStart, alignedEnd);\n            case MONTHLY -> splitMonthly(alignedStart, alignedEnd);\n        };\n    }\n\n    private static Instant floor(Instant instant, Granularity granularity) {\n        return switch (granularity) {\n            case HOURLY -> instant.truncatedTo(java.time.temporal.ChronoUnit.HOURS);\n            case DAILY -> instant.truncatedTo(java.time.temporal.ChronoUnit.DAYS);\n            case MONTHLY -> YearMonth.from(instant.atOffset(ZoneOffset.UTC))","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/ce/TimeBucketing.java#L51-L87","documentation":"Error \"End date must be after Start date.\" thrown in floci-io/floci.","triggerScenarios":"Thrown at src/main/java/io/github/hectorvent/floci/services/ce/TimeBucketing.java:69 when the library encounters an invalid state.","commonSituations":"Occurs when the TimePeriod End date is not strictly after the Start date. Provide an End date later than the Start date.","solutions":["Provide a TimePeriod where End is later than Start."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}