alibaba/canal · error · IOException

No binlog file header

Error message

No binlog file header

What it means

Thrown by FileLogFetcher.open() when reading the first BIN_LOG_HEADER_SIZE (4) bytes of a local binlog file returns fewer bytes than requested (or -1/EOF). The file is too short to even contain a binlog magic header, so it cannot be a valid binlog.

Source

Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/FileLogFetcher.java:79

        open(new File(filePath), 0L);
    }

    /**
     * Open binlog file in local disk to fetch.
     */
    public void open(String filePath, final long filePosition) throws FileNotFoundException, IOException {
        open(new File(filePath), filePosition);
    }

    /**
     * Open binlog file in local disk to fetch.
     */
    public void open(File file, final long filePosition) throws FileNotFoundException, IOException {
        fin = new FileInputStream(file);

        ensureCapacity(BIN_LOG_HEADER_SIZE);
        if (BIN_LOG_HEADER_SIZE != fin.read(buffer, 0, BIN_LOG_HEADER_SIZE)) {
            throw new IOException("No binlog file header");
        }

        if (buffer[0] != BINLOG_MAGIC[0] || buffer[1] != BINLOG_MAGIC[1] || buffer[2] != BINLOG_MAGIC[2]
            || buffer[3] != BINLOG_MAGIC[3]) {
            throw new IOException("Error binlog file header: "
                                  + Arrays.toString(Arrays.copyOf(buffer, BIN_LOG_HEADER_SIZE)));
        }

        limit = 0;
        origin = 0;
        position = 0;

        if (filePosition > BIN_LOG_HEADER_SIZE) {
            final int maxFormatDescriptionEventLen = FormatDescriptionLogEvent.LOG_EVENT_MINIMAL_HEADER_LEN
                                                     + FormatDescriptionLogEvent.ST_COMMON_HEADER_LEN_OFFSET
                                                     + LogEvent.ENUM_END_EVENT + LogEvent.BINLOG_CHECKSUM_ALG_DESC_LEN
                                                     + LogEvent.CHECKSUM_CRC32_SIGNATURE_LEN;

View on GitHub (pinned to 87be50e876)

Solutions

  1. Confirm the file path and that the file size is at least 4 bytes (and realistically >= the binlog header).
  2. Verify the file is a complete binlog produced by mysqld (ls -l, file size > 0), not a temp/partial file.
  3. Re-copy or re-fetch the binlog file from the master if it was truncated in transfer.
  4. Point FileLogFetcher at a fully flushed, closed binlog rather than the live one mysqld is writing.

Example fix

// before - opening whatever path was given
fetcher.open(new File(path), filePosition); // < 4 bytes -> No binlog file header

// after - sanity-check size first
File f = new File(path);
if (!f.isFile() || f.length() < 4) {
    throw new IOException("Not a binlog file (too short): " + f);
}
fetcher.open(f, filePosition);
Defensive patterns

Strategy: validation

Validate before calling

// Reject files too short to be binlogs before opening
File f = new File(path);
if (!f.isFile() || f.length() < 4) {
    throw new IOException("not a binlog (too short/missing): " + f);
}

Try / catch

try { fetcher.open(new File(path), pos); }
catch (IOException e) {
    if (e.getMessage().equals("No binlog file header"))
        throw new IOException("file is empty/truncated: " + path, e);
    throw e;
}

Prevention

When it happens

Trigger: new FileInputStream(file).read(buffer, 0, 4) returns a value != 4: the file is empty, < 4 bytes, or at EOF (the path points to an empty/partial file).

Common situations: Pointing at an empty file, a still-being-written/partial binlog, a rotated/renamed file, a directory or a non-binlog path, or a file truncated by disk-full / crash.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/11ce2c024644acf0. Report an issue: GitHub.