apache/druid · error · IOException
File[ ] is not a frame file
Error message
File[%s] is not a frame file
What it means
FrameFile.open validates that the target file begins with the FrameFileWriter magic bytes before reading any structure. If the first MAGIC.length bytes do not match, the file was not produced by the frame file writer (or its header was overwritten/truncated). The library throws this immediately to fail fast on non-frame input.
Solutions
- Verify the file path points to an actual frame file produced by FrameFileWriter (check the writer job output).
- Check the file size — a valid frame file must be at least TRAILER_LENGTH + header bytes; re-run the producing job if it is 0 or tiny.
- If the file should be a frame file, re-generate it; corruption of the header is not recoverable.
- Add a file-format/extension sanity check before opening files from user-supplied paths.
Example fix
// before
FrameFile.open(new File("output.json"), maxMmapSize);
// after
File f = new File("output.frame");
if (f.length() < FrameFileWriter.TRAILER_LENGTH + FrameFileWriter.MAGIC.length) {
throw new IllegalStateException("Not a frame file (too small): " + f);
}
FrameFile.open(f, maxMmapSize); Defensive patterns
Strategy: validation
Validate before calling
if (file == null || file.length() < FrameFileWriter.TRAILER_LENGTH) {
throw new IllegalArgumentException("Not a frame file (missing header/trailer): " + file);
} Type guard
static boolean looksLikeFrameFile(File f) {
return f.isFile() && f.length() >= FrameFileWriter.TRAILER_LENGTH;
} Try / catch
try {
FrameFile.open(file, maxMmapSize);
} catch (IOException e) {
// includes 'is not a frame file': regenerate or re-point to correct output
throw new UncheckedIOException("Invalid frame file: " + file, e);
} Prevention
- Only open files produced by FrameFileWriter; keep frame files in dedicated directories with a distinct extension.
- Check the producing task/segment status before reading its output.
- Use binary-safe transfers and verify sizes/checksums after copying.
- Never read a frame file while its writer is still running.
When it happens
Trigger: Calling FrameFile.open on a file that is empty, is a different file format, was truncated so the header bytes are missing, or whose leading bytes were modified after writing.
Common situations: Pointing a segment/frame reader at a log, JSON, or partially-written file; a job crashed mid-write leaving a zero-byte file; copying files with truncation; confusing two similarly-named output files.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Corrupt frame file: frame [%,d] location out of range
- Error while persisting
- Error while reading distribution for interval
- Exception while writing distribution file for interval
- Expected footer checksum did not match actual checksum…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b305fdd14693c925.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/frame/file/FrameFile.java:207
// Integer.MAX_VALUE) or entire file (if file size is smaller than, or equal to, Integer.MAX_VALUE).
Closeable sharedMapCloser = null;
try (final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
final long fileLength = randomAccessFile.length();
// Verify minimum file length.
if (fileLength <
FrameFileWriter.MAGIC.length + FrameFileWriter.TRAILER_LENGTH + Byte.BYTES /* MARKER_NO_MORE_FRAMES */) {
throw new IOE("File[%s] is too short (size[%,d])", file, fileLength);
}
// Verify magic.
final byte[] buf = new byte[FrameFileWriter.TRAILER_LENGTH /* Larger than FrameFileWriter.MAGIC */];
final Memory bufMemory = Memory.wrap(buf, ByteOrder.LITTLE_ENDIAN);
randomAccessFile.readFully(buf, 0, FrameFileWriter.MAGIC.length);
if (!bufMemory.equalTo(0, Memory.wrap(FrameFileWriter.MAGIC), 0, FrameFileWriter.MAGIC.length)) {
throw new IOE("File[%s] is not a frame file", file);
}
// Read number of frames and partitions.
randomAccessFile.seek(fileLength - FrameFileWriter.TRAILER_LENGTH);
randomAccessFile.readFully(buf, 0, FrameFileWriter.TRAILER_LENGTH);
final int footerLength = bufMemory.getInt(Integer.BYTES * 2L);
if (footerLength < 0) {
throw new ISE("Negative-size footer. Corrupt or truncated file[%s]?", file);
} else if (footerLength > fileLength) {
throw new ISE("Oversize footer. Corrupt or truncated file[%s]?", file);
}
final Memory wholeFileMemory;
final Memory footerMemory;
if (fileLength <= maxMmapSize) {
// Map entire file, use region for footer.View on GitHub (pinned to 9b90983fd2)