apache/seatunnel · error · RuntimeException
shard cursor error
Error message
shard cursor error
What it means
The SLS (Aliyun Log Service) source split enumerator builds a shard read cursor during split assignment and throws this if the resolved cursor string is empty. An empty cursor means the consumer position could not be resolved from the log service, so the split would read nothing or behave unpredictably.
Solutions
- Check that the logStore and shard contain data for the configured cursor mode (e.g. begin/end/timestamp).
- Verify cursorMode and autoCursorReset options are valid values supported by the SLS SDK.
- Ensure the SLS credentials (project, accessKey) allow GetCursor on the logstore.
- Add logging around initShardCursor to see which mode returned the empty cursor and retry with an explicit valid cursor mode.
Example fix
// before
if (cursor.equals("")) {
throw new RuntimeException("shard cursor error");
}
// after
if (cursor == null || cursor.isEmpty()) {
throw new IllegalStateException(
"SLS returned an empty cursor for shard " + shardIdKey
+ " in logStore " + logStore + " with cursorMode " + cursorMode
+ "; verify the shard has readable data or set autoCursorReset appropriately");
} Defensive patterns
Strategy: validation
Validate before calling
String cursor = initShardCursor(...); if (cursor == null || cursor.isEmpty()) { throw new IllegalStateException("empty SLS cursor for " + logStore + "/shard " + shardIdKey + ", cursorMode=" + cursorMode); } Try / catch
try { enumerator.discoverySplits(); } catch (RuntimeException e) { if (String.valueOf(e.getMessage()).contains("shard cursor error")) { log.error("SLS shard cursor empty; check cursorMode/data", e); throw new ConfigurationException(...); } throw e; } Prevention
- Verify the logStore has shards with readable data for the chosen cursor mode
- Test GetCursor manually against the SLS endpoint before running the pipeline
- Pin explicit cursorMode/autoCursorReset values in config rather than relying on fallbacks
When it happens
Trigger: fetchPendingShardSplit (called from discoverySplits) constructs a cursor via initShardCursor; if GetCursor succeeds through all cursor modes but the returned cursor string equals "", the RuntimeException is thrown.
Common situations: Empty logStore shards with no readable data for the requested cursor mode; misconfigured autoCursorReset values; logstore recently created/truncated so no cursor exists for the given mode.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- : : : :fail
- Change stream cursor has expired, trying to recreate cursor
- checkpoint do not exist or have already been committed.
- COMMON_ERROR_CODE.UNSUPPORTED_OPERATION
- Failed to read AmazonDocumentDB data from database
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/5207a2d5418c0a57.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-sls/src/main/java/org/apache/seatunnel/connectors/seatunnel/sls/source/SlsSourceSplitEnumerator.java:195
.forEach(
shard -> {
if (!assignedSplit.containsKey(shard.getShardId())) {
if (!pendingSplit.containsKey(shard.getShardId())) {
String cursor = "";
try {
cursor =
initShardCursor(
project,
logStore,
consumer,
shard.getShardId(),
startMode,
autoCursorReset);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (cursor.equals("")) {
throw new RuntimeException("shard cursor error");
}
SlsSourceSplit split =
new SlsSourceSplit(
project,
logStore,
consumer,
shard.getShardId(),
cursor,
fetachSize);
pendingSplit.put(shard.getShardId(), split);
}
}
});
}
private String initShardCursor(
String project,
String logStore,View on GitHub (pinned to cf67b549a7)