apache/seatunnel · warning
Tunnel deletion failed due to not found:
Error message
Tunnel deletion failed due to not found:
What it means
TableStoreSourceReader.deleteTunel deletes the OTS tunnel associated with a finished split. If tunnelClient.deleteTunnel throws (typically because the tunnel no longer exists, TableStore error code OTSObjectNotExist), the reader only logs this warning and swallows the exception. The connector treats 'already gone' as success so snapshot cleanup is idempotent.
Solutions
- No action required if the tunnel is intentionally gone — the warning is expected on idempotent cleanup.
- Check the OTS console to confirm the tunnel for the table no longer exists and no consumer groups still need it.
- If deletions fail persistently with other errors, inspect the swallowed exception `be` (add logging of be.getMessage()) to distinguish not-found from permission/network failures.
Example fix
// before: exception details are swallowed
} catch (Exception be) {
log.warn("Tunnel deletion failed due to not found: " + tunnelName);
}
// after: log the cause for diagnosability
} catch (Exception be) {
log.warn("Tunnel deletion failed for tunnel {}: {}", tunnelName, be.getMessage(), be);
} Defensive patterns
Strategy: try-catch
Validate before calling
// before deleting, check tunnel exists ListTunnelResponse lresp = tunnelClient.listTunnel(new ListTunnelRequest(tableName)); boolean exists = lresp.getTunnels().stream().anyMatch(t -> t.getTunnelName().equals(tunnelName));
Try / catch
try {
tunnelClient.deleteTunnel(drequest);
} catch (TableStoreException e) {
if (!"OTSObjectNotExist".equals(e.getErrorCode())) {
throw e; // only swallow genuine not-found
}
} Prevention
- Only treat OTSObjectNotExist as an expected skip; rethrow other errors
- Log the swallowed exception's message/cause for diagnosability
- Avoid manual tunnel deletion while a reader job is active
When it happens
Trigger: deleteTunel(split, tunnelName) is called (from getTunel cleanup after a split is fully consumed) and the tunnel was already deleted — e.g. by a previous checkpoint restart, a parallel reader instance, or manual cleanup — so TableStore returns a not-found error.
Common situations: Job restarted after tunnel deletion succeeded but before state was committed; two readers racing to clean up the same tunnel; operator deleted tunnels manually via the OTS console while the job was running.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- CLOSE_CONNECTION_FAILED
- close easysearch connection error
- close elasticsearch connection error
- CLOSE_FAILED
- Close JDBC writer failed.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/ae8e4dfd737ec845.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-tablestore/src/main/java/org/apache/seatunnel/connectors/seatunnel/tablestore/source/TableStoreSourceReader.java:154
CreateTunnelRequest crequest =
new CreateTunnelRequest(
split.getTableName(), tunnelName, TunnelType.valueOf("BaseAndStream"));
CreateTunnelResponse cresp = tunnelClient.createTunnel(crequest);
tunnelId = cresp.getTunnelId();
}
log.info("Tunnel found, Id: " + tunnelId);
return tunnelId;
}
public void deleteTunel(TableStoreSourceSplit split) {
String tunnelName = split.getTableName() + "_migration2aws_tunnel4" + split.getSplitId();
try {
DeleteTunnelRequest drequest =
new DeleteTunnelRequest(split.getTableName(), tunnelName);
DeleteTunnelResponse dresp = tunnelClient.deleteTunnel(drequest);
log.info("Tunnel has been deleted: " + dresp.toString());
} catch (Exception be) {
log.warn("Tunnel deletion failed due to not found: " + tunnelName);
}
}
@Override
public List<TableStoreSourceSplit> snapshotState(long checkpointId) throws Exception {
return new ArrayList<>(pendingSplits);
}
@Override
public void addSplits(List<TableStoreSourceSplit> splits) {
this.pendingSplits.addAll(splits);
}
@Override
public void handleNoMoreSplits() {
log.info("Reader [{}] received noMoreSplit event.", context.getIndexOfSubtask());
noMoreSplit = true;
}View on GitHub (pinned to cf67b549a7)