apache/seatunnel · error · RuntimeException

: : : :fail

Error message

${project}:${logStore}:${consumer}:${cursorMode}:fail

What it means

initShardCursor tries each cursor initialization mode in turn when resolving a shard cursor from Aliyun Log Service. If every mode throws, the method falls through its switch and throws this RuntimeException listing project, logStore, consumer, and cursorMode to indicate cursor initialization failed entirely.

Solutions

  1. Check the log for the wrapped original exception (`throw new RuntimeException(e)`) to see the underlying SLS error.
  2. Verify cursorMode is one of the supported values for the SLS source config.
  3. Confirm the project/logStore names are correct and the credentials have read permissions.
  4. Ensure the shard id exists on the logstore (shard may have been merged/split).

Example fix

// before
throw new RuntimeException(
    project + ":" + logStore + ":" + consumer + ":" + cursorMode + ":" + "fail");
// after
throw new RuntimeException(
    "Failed to initialize shard cursor (project=" + project + ", logStore=" + logStore
    + ", consumer=" + consumer + ", cursorMode=" + cursorMode + ")", e);
Defensive patterns

Strategy: try-catch

Validate before calling

try { client.GetCursor(project, logStore, shardId, mode).GetCursor(); } catch (LogException e) { /* pre-flight check of mode, shard existence, permissions */ }

Try / catch

try { initShardCursor(...); } catch (RuntimeException e) { log.error("SLS cursor init failed for project={} logStore={} consumer={} cursorMode={}", project, logStore, consumer, cursorMode, e.getCause()); throw e; }

Prevention

When it happens

Trigger: Called from fetchPendingShardSplit; any exception inside the per-mode GetCursor calls (e.g. from .GetCursor(project, logStore, shardIdKey, autoCursorReset).GetCursor()) is caught and the loop/fallthrough ends at this throw, meaning no cursor mode succeeded.

Common situations: Invalid cursorMode option value; SLS API errors such as LogStoreNotExist, unauthorized access, or shard id out of range; network/auth failures talking to the SLS endpoint.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/ba20d42ca0edb777. 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:263

                    if (checkpoints.size() == 1) {
                        ConsumerGroupShardCheckPoint checkpoint = checkpoints.get(0);
                        if (!checkpoint.getCheckPoint().equals("")) {
                            return checkpoint.getCheckPoint();
                        }
                    }
                    return this.slsCleint
                            .GetCursor(project, logStore, shardIdKey, autoCursorReset)
                            .GetCursor();
                } catch (LogException e) {
                    if (e.GetErrorCode().equals("ConsumerGroupNotExist")) {
                        return this.slsCleint
                                .GetCursor(project, logStore, shardIdKey, autoCursorReset)
                                .GetCursor();
                    }
                    throw new RuntimeException(e);
                }
        }
        throw new RuntimeException(
                project + ":" + logStore + ":" + consumer + ":" + cursorMode + ":" + "fail");
    }

    private synchronized void assignSplit() {
        Map<Integer, List<SlsSourceSplit>> readySplit = new HashMap<>(Common.COLLECTION_SIZE);
        // init task from Parallelism
        for (int taskID = 0; taskID < context.currentParallelism(); taskID++) {
            readySplit.computeIfAbsent(taskID, id -> new ArrayList<>());
        }
        // Determine if split has been assigned
        pendingSplit.forEach(
                (key, value) -> {
                    if (!assignedSplit.containsKey(key)) {
                        readySplit
                                .get(
                                        getSplitOwner(
                                                value.getShardId(), context.currentParallelism()))
                                .add(value);

View on GitHub (pinned to cf67b549a7)