alibaba/canal · critical · PositionNotFoundException

position timestamp is empty!

Error message

position timestamp is empty!

What it means

Thrown as PositionNotFoundException by RdsLocalBinlogEventParser.start() when the start position IS found (non-null) but its timestamp field is null or <= 0. The timestamp is needed to determine the time range for querying RDS binlog backup files.

Source

Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/rds/RdsLocalBinlogEventParser.java:61

    public void start() throws CanalParseException {
        try {
            Assert.notNull(accesskey);
            Assert.notNull(secretkey);
            Assert.notNull(instanceId);
            Assert.notNull(url);
            Assert.notNull(directory);

            if (endTime == null) {
                endTime = System.currentTimeMillis();
            }

            EntryPosition entryPosition = findStartPosition(null);
            if (entryPosition == null) {
                throw new PositionNotFoundException("position not found!");
            }
            Long startTimeInMill = entryPosition.getTimestamp();
            if (startTimeInMill == null || startTimeInMill <= 0) {
                throw new PositionNotFoundException("position timestamp is empty!");
            }

            startTime = startTimeInMill;
            List<BinlogFile> binlogFiles = RdsBinlogOpenApi.listBinlogFiles(url,
                accesskey,
                secretkey,
                instanceId,
                new Date(startTime),
                new Date(endTime));
            if (binlogFiles.isEmpty()) {
                throw new CanalParseException("start timestamp : " + startTimeInMill + " binlog files is empty");
            }

            binlogDownloadQueue = new BinlogDownloadQueue(binlogFiles, batchFileSize, directory);
            binlogDownloadQueue.silenceDownload();
            needWait = true;
            // try to download one file,use to test server id
            binlogDownloadQueue.tryOne();

View on GitHub (pinned to 87be50e876)

Solutions

  1. Clear the existing position data and re-seed it with a valid timestamp matching a known binlog event time.
  2. If using a custom LogPositionManager, ensure EntryPosition.setTimestamp() is called with a valid epoch millisecond value.
  3. Upgrade the position data to include timestamp, or manually patch the stored position JSON/XML.
  4. As a last resort, delete the position and start fresh with a configured start time.
Defensive patterns

Strategy: validation

Validate before calling

// Before starting, validate the position has a timestamp
EntryPosition pos = logPositionManager.getLatestIndexBy(destination);
if (pos != null && (pos.getTimestamp() == null || pos.getTimestamp() <= 0)) {
    pos.setTimestamp(System.currentTimeMillis() - 86400000L); // set to yesterday
    logPositionManager.persistLogPosition(destination, buildLogPosition(pos));
}

Try / catch

try {
    parser.start();
} catch (PositionNotFoundException e) {
    if (e.getMessage().contains("timestamp is empty")) {
        // patch the position with a valid timestamp and retry
    }
}

Prevention

When it happens

Trigger: findStartPosition returns an EntryPosition object, but getTimestamp() returns null or a value <= 0. This happens when the persisted position lacks timestamp metadata — e.g., it was created by a parser that only recorded journal name and offset without a server timestamp.

Common situations: Position was persisted by an older canal version or different parser type that did not populate the timestamp field; position data was manually edited or corrupted; migration from a different position format that dropped the timestamp.

Related errors


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