alibaba/canal · error · IOException

Error binlog file header: {}

Error message

Error binlog file header: {}

What it means

Thrown by FileLogFetcher.open() after reading exactly 4 header bytes that do not equal BINLOG_MAGIC ({0xfe, 'b','i','n'}). The file is long enough to have a header, but the magic bytes are wrong, so it is not a MySQL binlog file.

Source

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

     */
    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;

            ensureCapacity(maxFormatDescriptionEventLen);
            limit = fin.read(buffer, 0, maxFormatDescriptionEventLen);
            limit = (int) getUint32(LogEvent.EVENT_LEN_OFFSET);
            fin.getChannel().position(filePosition);
        }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Inspect the printed byte array in the message; {-2,98,105,110} would be correct magic, so any deviation confirms wrong content.
  2. Ensure the path is the raw mysqld binlog (typically mysql-bin.NNNNNN), not a .gz/.zip/.index/.sql sibling.
  3. Decompress first if the binlog was archived as gzip.
  4. Re-fetch the binlog from the master if the on-disk copy is the wrong file.

Example fix

// before
fetcher.open(new File(path), pos); // first 4 bytes != {0xfe,'b','i','n'}

// after - decompress archived binlogs before opening
File target = path.endsWith(".gz") ? gunzipTo(path) : new File(path);
fetcher.open(target, pos);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the binlog magic before handing the file to the fetcher
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
    byte[] m = new byte[4];
    raf.readFully(m);
    if (m[0] != -2 || m[1] != 'b' || m[2] != 'i' || m[3] != 'n')
        throw new IOException("not a binlog (bad magic): " + file);
}

Try / catch

try { fetcher.open(file, pos); }
catch (IOException e) {
    if (e.getMessage().startsWith("Error binlog file header"))
        throw new IOException("wrong file type - decompress if gz / pick the raw mysql-bin.NNNNNN", e);
    throw e;
}

Prevention

When it happens

Trigger: FileLogFetcher reads 4 bytes into buffer and compares against BINLOG_MAGIC; the first four bytes differ (e.g. a gzip/relay-log.index/SQL text file), so it raises IOException with the offending bytes printed.

Common situations: Passing a compressed binlog (.gz), a relay-log index file, a plain SQL dump, a binary from a different engine, or a file with a byte-order mark prepended; reading the wrong file in a directory of similarly named files.

Related errors


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