{"record":{"id":"e05bca22a6241fb2","repo":"prestodb/presto","slug":"nanos-must-be-in-range-0-999-999-999","errorCode":null,"errorMessage":"nanos must be in range [0, 999_999_999]: ","messagePattern":"nanos must be in range \\[0, 999_999_999\\]: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/type/TimestampType.java","lineNumber":204,"sourceCode":"    // Supported for all short precisions (p=0 through p=6, i.e. isShort()==true).\n    // Long precisions (p=7-12) require a 128-bit representation and are not yet supported.\n    public long toEpochMicros(long timestamp)\n    {\n        if (!isShort()) {\n            throw new UnsupportedOperationException(\n                    \"toEpochMicros is not supported for TIMESTAMP(\" + precision + \")\");\n        }\n        return getEpochSecond(timestamp) * 1_000_000L + getNanos(timestamp) / 1_000;\n    }\n\n    public long fromEpochComponents(long epochSecond, int nanos)\n    {\n        if (!isShort()) {\n            throw new UnsupportedOperationException(\n                    \"fromEpochComponents is not supported for TIMESTAMP(\" + precision + \")\");\n        }\n        if (nanos < 0 || nanos >= 1_000_000_000) {\n            throw new IllegalArgumentException(\"nanos must be in range [0, 999_999_999]: \" + nanos);\n        }\n        long scale = PRECISION_SCALE[precision];\n        return epochSecond * scale + nanos / (1_000_000_000L / scale);\n    }\n\n    private static TimeUnit toTimeUnit(int precision)\n    {\n        // Exact-precision checks: DEFAULT_PRECISION (3) stores epoch-millis; MAX_SHORT_PRECISION (6)\n        // stores epoch-micros. Other precisions have no direct TimeUnit mapping.\n        if (precision == DEFAULT_PRECISION) {\n            return MILLISECONDS;\n        }\n        if (precision == MAX_SHORT_PRECISION) {\n            return MICROSECONDS;\n        }\n        throw new UnsupportedOperationException(\n                \"Unsupported precision for TimeUnit conversion: TIMESTAMP(\" + precision + \")\");\n    }","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/type/TimestampType.java#L186-L222","documentation":"fromEpochComponents validates that the nanos fraction is a sub-second value in [0, 999_999_999]. Values outside that range cannot represent a fractional-second component and would corrupt the packed timestamp, so IllegalArgumentException is thrown.","triggerScenarios":"Calling fromEpochComponents(epochSecond, nanos) with nanos negative (e.g. -1) or >= 1_000_000_000 (e.g. 1_000_000_000, meaning the carry belongs in epochSecond).","commonSituations":"Code that carries overflow from fractional arithmetic into nanos instead of into the seconds field; unit conversions passing milliseconds/microseconds without scaling to nanoseconds.","solutions":["Normalize the components: fold nanos >= 1e9 into epochSecond (epochSecond += nanos / 1e9; nanos %= 1e9) before calling.","Scale other units (ms, us) to nanoseconds before passing them.","Validate/normalize inputs with Math.floorDiv / Math.floorMod to keep them in range."],"exampleFix":"// before\nlong ts = type.fromEpochComponents(epochSecond, nanos);\n// after\nepochSecond += Math.floorDiv(nanos, 1_000_000_000);\nnanos = Math.floorMod(nanos, 1_000_000_000);\nlong ts = type.fromEpochComponents(epochSecond, nanos);","handlingStrategy":"validation","validationCode":"if (nanos < 0 || nanos >= 1_000_000_000) {\n    epochSecond += Math.floorDiv(nanos, 1_000_000_000);\n    nanos = Math.floorMod(nanos, 1_000_000_000);\n}","typeGuard":"boolean isValidNanos(int nanos) { return nanos >= 0 && nanos < 1_000_000_000; }","tryCatchPattern":"try {\n    packed = type.fromEpochComponents(epochSecond, nanos);\n} catch (IllegalArgumentException e) {\n    packed = type.fromEpochComponents(\n        epochSecond + Math.floorDiv(nanos, 1_000_000_000),\n        Math.floorMod(nanos, 1_000_000_000));\n}","preventionTips":["Always normalize fractional seconds with floorDiv/floorMod before composing timestamps.","Convert ms/us inputs to nanoseconds with explicit scaling constants.","Add boundary tests for nanos = -1, 0, 999_999_999, and 1_000_000_000."],"tags":["presto","illegal-argument","timestamp","range-check"],"backgroundTag":"invalid-argument-range","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}