prestodb/presto · error · IllegalArgumentException
nanos field of an encoded timestamp in ORC must be between 0
Error message
nanos field of an encoded timestamp in ORC must be between 0 and 999999999 inclusive, got
What it means
This IllegalArgumentException is thrown by ApacheHiveTimestampDecoder.decodeTimestamp when a TIMESTAMP value read from an ORC file carries a nanos component outside the valid 0..999999999 range. ORC encodes nanos-of-second as a non-negative value below one second, so an out-of-range value means the encoded data is malformed or decoded incorrectly. It guards Presto's internal timestamp arithmetic from a corrupt nanos field.
Source
Thrown at presto-orc/src/main/java/com/facebook/presto/orc/reader/ApacheHiveTimestampDecoder.java:30
* limitations under the License.
*/
package com.facebook.presto.orc.reader;
import com.facebook.presto.orc.DecodeTimestampOptions;
final class ApacheHiveTimestampDecoder
{
private ApacheHiveTimestampDecoder() {}
// This comes from the Apache Hive ORC code
public static long decodeTimestamp(long seconds, long serializedNanos, DecodeTimestampOptions options)
{
boolean enableMicroPrecision = options.enableMicroPrecision();
long secondsWithBase = seconds + options.getBaseSeconds();
long value = getSecondsInRequiredUnits(enableMicroPrecision, secondsWithBase, options.getUnitsPerSecond());
long nanos = parseNanos(serializedNanos);
if (nanos > 999999999 || nanos < 0) {
throw new IllegalArgumentException("nanos field of an encoded timestamp in ORC must be between 0 and 999999999 inclusive, got " + nanos);
}
// the rounding error exists because java always rounds up when dividing integers
// -42001/1000 = -42; and -42001 % 1000 = -1 (+ 1000)
// to get the correct value we need
// (-42 - 1)*1000 + 999 = -42001
// (42)*1000 + 1 = 42001
if (value < 0 && nanos != 0) {
value -= options.getUnitsPerSecond();
}
// Truncate nanos to required units (millis / micros)
long truncatedNanos = nanos / options.getNanosPerUnit();
return getValueWithNanos(enableMicroPrecision, value, truncatedNanos);
}
private static long getSecondsInRequiredUnits(boolean enableMicroPrecision, long secondsWithBase, long unitsPerSecond)
{
if (!enableMicroPrecision) {View on GitHub (pinned to 55bb57d202)
Solutions
- Verify the ORC file is not corrupted; rewrite the file with a trusted writer (e.g. current Hive or Presto itself).
- Check the writer version/tool that produced the ORC file for known timestamp encoding bugs and upgrade it.
- Confirm nanosOfSecond encoding settings in the writer are standard (max nano precision not misconfigured).
- Validate the file with an ORC metadata/scan tool (orc-tools) to locate the corrupt stripe.
Example fix
// before: reading suspect file directly Cursor cursor = reader.read(); // after: validate file first with orc-tools, then rewrite // hive --orcfiledump bad.orc -> find corrupt stripe // rewrite: INSERT INTO clean_table SELECT ... FROM bad_table;
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate ORC file timestamps before query // orc-tools scan file.orc -- check TIMESTAMP columns decode cleanly
Type guard
boolean isValidNanos(long nanos) { return nanos >= 0 && nanos <= 999999999; } Try / catch
try { ts = decoder.decodeTimestamp(...); } catch (IllegalArgumentException e) { log.error("corrupt ORC timestamp nanos", e); ts = null; } Prevention
- Write ORC files only with well-known, up-to-date writers
- Validate files with orc-tools before loading into Presto
- Avoid hand-rolled ORC writers for timestamp columns
- Checksum files on transfer to detect corruption
When it happens
Trigger: Reading an ORC TIMESTAMP column whose serialized nanos field, after parseNanos decoding, is negative or greater than 999999999 — i.e. decoding a corrupt or non-standard ORC file with decodeTimestamp().
Common situations: Files written by buggy or third-party ORC writers that encode nanos incorrectly; files corrupted in transit/storage; reading files produced by incompatible Hive/ORC versions with divergent timestamp encodings.
Related errors
- seconds field of timestamp exceeds maximum supported value,
- Timestamp exceeds maximum supported value, value: %s truncat
- Read past end of RLE integer
- Invalid RLEv2 encoded stream
- Decoded value out of range for a 32bit number
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/f7ff24f1241456b9.
Report an issue: GitHub.