{"record":{"id":"ac7c5b201b1db93c","repo":"elastic/elasticsearch","slug":"failed-to-parse-fractional-time-values-are-n","errorCode":null,"errorMessage":"failed to parse [{}], fractional time values are not supported","messagePattern":"failed to parse \\[(.+?)\\], fractional time values are not supported","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/core/src/main/java/org/elasticsearch/core/TimeValue.java","lineNumber":429,"sourceCode":"        final String s = normalized.substring(0, normalized.length() - suffix.length()).trim();\n        try {\n            final long value = Long.parseLong(s);\n            if (value < -1) {\n                // -1 is magic, but reject any other negative values\n                throw new IllegalArgumentException(\n                    \"failed to parse setting [\"\n                        + settingName\n                        + \"] with value [\"\n                        + initialInput\n                        + \"] as a time value: negative durations are not supported\"\n                );\n            }\n            return value;\n        } catch (final NumberFormatException e) {\n            try {\n                @SuppressWarnings(\"unused\")\n                final double ignored = Double.parseDouble(s);\n                throw new IllegalArgumentException(\"failed to parse [\" + initialInput + \"], fractional time values are not supported\", e);\n            } catch (final NumberFormatException ignored) {\n                throw new IllegalArgumentException(\"failed to parse [\" + initialInput + \"]\", e);\n            }\n        }\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        return this.compareTo(((TimeValue) o)) == 0;\n    }\n\n    @Override\n    public int hashCode() {\n        return Double.hashCode(((double) duration) * timeUnit.toNanos(1));\n    }","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/core/src/main/java/org/elasticsearch/core/TimeValue.java#L411-L447","documentation":"Thrown by TimeValue.parse when the numeric prefix of a time value fails Long.parseLong but succeeds as Double.parseDouble — i.e. the user supplied a fractional number. TimeValue stores durations as a long plus a TimeUnit, so fractional values are fundamentally unsupported. The original NumberFormatException is chained as the cause for diagnostics.","triggerScenarios":"Passing a fractional duration string such as \"1.5s\", \"0.5d\", \"2.25h\", \".5ms\" to any code path that calls TimeValue.parseTimeValue. Fires at TimeValue.java:429 in the inner try after Double.parseDouble(s) succeeds.","commonSituations":"Converting a float/double timeout (e.g. from a JSON payload or a metrics-derived value) directly to a string without rounding. Migrating configs from systems that accept fractional seconds (Python's timedelta, ISO-8601 durations). Tooling that does String.valueOf(2.5) + \"s\".","solutions":["Round or truncate to a whole number of the smallest needed unit, e.g. convert 1.5s to 1500ms.","If the source is a double, scale and cast: long ms = (long) Math.round(seconds * 1000); then format ms + \"ms\".","Replace the fractional literal in elasticsearch.yml or the settings API with an integer-equivalent duration.","Validate user-supplied time strings with a regex like ^-?\\d+[a-z]+$ before forwarding them to TimeValue."],"exampleFix":"// before\nString t = \"1.5s\";\nTimeValue.parseTimeValue(t, \"x\");\n\n// after — scale to milliseconds\nString t = Math.round(1.5 * 1000) + \"ms\"; // \"1500ms\"","handlingStrategy":"validation","validationCode":"// Reject fractional magnitudes before parsing\nstatic String requireIntegralDuration(String s) {\n    String body = s.toLowerCase(Locale.ROOT).trim().replaceAll(\"(ns|us|micros|ms|s|m|h|d)$\", \"\");\n    if (body.matches(\".*[.e].*\")) throw new IllegalArgumentException(\"fractional not allowed: \" + s);\n    return s;\n}","typeGuard":"static boolean isIntegralTimeValue(String s) {\n    if (s == null) return false;\n    String n = s.trim().toLowerCase(Locale.ROOT);\n    return n.matches(\"-?\\\\d+(ns|us|micros|ms|s|m|h|d)\") || n.equals(\"-1\") || n.matches(\"0+\");\n}","tryCatchPattern":"try {\n    TimeValue.parseTimeValue(raw, setting);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"fractional\")) {\n        // rescale: parse the double, convert to smallest integer unit\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never concatenate a float/double into a time string; scale to an integral unit first.","When accepting timeouts from JSON, type them as integer milliseconds or as ISO durations.","In tests, fuzz time-value inputs to catch fractional edge cases.","Document for API consumers that durations are integer + unit."],"tags":["time-value","settings","configuration","parse","fractional","elasticsearch-core"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}