alibaba/spring-ai-alibaba · error · RuntimeException
Failed to delete dataset version
Error message
Failed to delete dataset version
What it means
After passing the null/existence/PUBLISHED checks, deleteById() executes datasetVersionMapper.deleteById(id) and throws RuntimeException("Failed to delete dataset version") when the affected-row count is <= 0. This indicates the DELETE statement removed no rows despite the earlier existence check — typically a race with a concurrent deletion or a mapper/SQL issue.
Source
Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/service/impl/DatasetVersionServiceImpl.java:195
public void deleteById(Long id) {
log.info("Deleting dataset version: {}", id);
if (id == null) {
throw new IllegalArgumentException("Version ID cannot be null");
}
DatasetVersionDO existingVersion = datasetVersionMapper.selectById(id);
if (existingVersion == null) {
throw new IllegalArgumentException("Dataset version not found: " + id);
}
if ("PUBLISHED".equals(existingVersion.getStatus())) {
throw new IllegalStateException("Cannot delete published version: " + id);
}
int result = datasetVersionMapper.deleteById(id);
if (result <= 0) {
throw new RuntimeException("Failed to delete dataset version");
}
log.info("Dataset version deleted successfully: {}", id);
}
@Override
public PageResult<Experiment> getExperiments(DatasetExperimentsListRequest request) {
long offset = (request.getPageNumber() - 1L) * request.getPageSize();
List<ExperimentDO> experimentDOList = experimentMapper.selectByDatasetId(request.getDatasetId(), offset, request.getPageSize());
Integer totalCount = experimentMapper.selectCountByDatasetId(request.getDatasetId());
return new PageResult<>(
(long) totalCount,
(long) request.getPageNumber(),
(long) request.getPageSize(),
experimentDOList.stream()View on GitHub (pinned to f82da0b50f)
Solutions
- Retry once: if the version is gone, the delete already succeeded elsewhere — treat as success.
- Verify the mapper's deleteById SQL targets the correct table.
- Wrap delete in a short transaction or use DELETE ... WHERE id=? rowcount semantics with idempotent handling.
Example fix
// before
int result = datasetVersionMapper.deleteById(id);
if (result <= 0) { throw new RuntimeException("Failed to delete dataset version"); }
// after
int result = datasetVersionMapper.deleteById(id);
if (result <= 0 && datasetVersionMapper.selectById(id) != null) {
throw new RuntimeException("Failed to delete dataset version");
} // else: already deleted concurrently — idempotent success Defensive patterns
Strategy: retry
Validate before calling
if (service.getById(id) == null) {
return; // nothing to delete
} Try / catch
try {
service.deleteById(id);
} catch (RuntimeException e) {
if (service.getById(id) == null) {
log.info("Version {} already deleted concurrently", id);
} else { throw e; }
} Prevention
- Handle deletes idempotently: row-count 0 plus row-gone means success.
- Avoid concurrent admin sessions deleting the same version; use soft-delete flags if concurrency is common.
- Keep mapper delete SQL aligned with the actual table schema after migrations.
When it happens
Trigger: Another transaction deleted the version between the selectById existence check and deleteById; the mapper's delete SQL is misconfigured or filtered; database-level failure reported as 0 affected rows.
Common situations: Concurrent admin sessions deleting the same version; retry logic that double-executes deletes; Flyway/migration changes altering table names the mapper still targets.
Related errors
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/2c06cf1622d07f81.
Report an issue: GitHub.