apache/seatunnel · error · DorisConnectorException
STREAM_LOAD_FAILED
STREAM_LOAD_FAILED
Error message
Load status is LABEL_ALREADY_EXIST and load job finished, change you label prefix or restore from latest savepoint!
What it means
During 2PC pre-commit (abortPreCommit in DorisStreamLoad), if Doris returns LABEL_ALREADY_EXIST and the existing job's status is JOB_EXIST_FINISHED, the previous label's transaction is already committed — it cannot be aborted. The library tells the user to change the label prefix or restore from the latest savepoint.
Source
Thrown at seatunnel-connectors-v2/connector-doris/src/main/java/org/apache/seatunnel/connectors/doris/sink/writer/DorisStreamLoad.java:165
.setLabel(label)
.setEmptyEntity()
.addProperties(streamLoadProp);
RespContent respContent =
handlePreCommitResponse(
HttpUtil.executeWithRedirectTracking(
httpClient,
builder.build(),
loadUrlStr,
directToBe,
enable2PC,
"pre-commit"),
"pre-commit",
loadUrlStr);
checkState("true".equals(respContent.getTwoPhaseCommit()));
if (LoadStatus.LABEL_ALREADY_EXIST.equals(respContent.getStatus())) {
// label already exist and job finished
if (JOB_EXIST_FINISHED.equals(respContent.getExistingJobStatus())) {
throw new DorisConnectorException(
DorisConnectorErrorCode.STREAM_LOAD_FAILED,
"Load status is "
+ LoadStatus.LABEL_ALREADY_EXIST
+ " and load job finished, "
+ "change you label prefix or restore from latest savepoint!");
}
// job not finished, abort.
Matcher matcher = LABEL_EXIST_PATTERN.matcher(respContent.getMessage());
if (matcher.find()) {
checkState(label.equals(matcher.group(1)));
long txnId = Long.parseLong(matcher.group(2));
log.info("abort {} for exist label {}", txnId, label);
abortTransaction(txnId);
} else {
throw new DorisConnectorException(
DorisConnectorErrorCode.STREAM_LOAD_FAILED,
"Load Status is "
+ LoadStatus.LABEL_ALREADY_EXISTView on GitHub (pinned to cf67b549a7)
Solutions
- Restore the job from the latest savepoint/checkpoint instead of an older one
- Change the label prefix (label-prefix config) to a new unique value
- If the duplicate load is confirmed already committed, skip/advance past that checkpoint
- Clean up duplicates in the target table before rerunning with a new prefix
Example fix
// before
sink {
Doris {
label-prefix = "st_job"
}
}
// after
sink {
Doris {
label-prefix = "st_job_2026_09_10_v2"
}
} Defensive patterns
Strategy: try-catch
Try / catch
try { /* restore/restart job */ } catch (DorisConnectorException e) { if (e.getMessage().contains("LABEL_ALREADY_EXIST")) { /* restore from latest savepoint or change label-prefix */ } throw e; } Prevention
- Always restore from the latest savepoint, not an old checkpoint
- Give each job/deployment a unique label-prefix
- Never reuse a label-prefix across concurrent jobs
- Monitor for label collisions after manual restarts
When it happens
Trigger: Job restored/restarted and the generated label (label prefix + checkpoint id) matches a label whose load already FINISHED on Doris; abortPreCommit receives the two-phase-commit response with status LABEL_ALREADY_EXIST and existingJobStatus FINISHED.
Common situations: Replaying a job from an old savepoint/checkpoint after the data was already successfully loaded; label prefix reused across two jobs; checkpoint id collision after manual restarts.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/808919ec510205a4.
Report an issue: GitHub.