apache/dolphinscheduler · error · ServiceException
20004
20004
Error message
resource not exist
What it means
updateDataSource looks up the target by id via dataSourceDao.queryById; when no record matches, Status.RESOURCE_NOT_EXIST (code 20004) is thrown, meaning the datasource id in the request does not exist.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataSourceServiceImpl.java:129
dataSource.setType(datasourceParam.getType());
dataSource.setConnectionParams(JSONUtils.toJsonString(connectionParam));
dataSource.setCreateTime(now);
dataSource.setUpdateTime(now);
try {
dataSourceDao.insert(dataSource);
return dataSource;
} catch (DuplicateKeyException ex) {
throw new ServiceException(Status.DATASOURCE_EXIST);
}
}
@Override
public DataSource updateDataSource(User loginUser, BaseDataSourceParamDTO dataSourceParam) {
DataSourceUtils.checkDatasourceParam(dataSourceParam);
// determine whether the data source exists
DataSource dataSource = dataSourceDao.queryById(dataSourceParam.getId());
if (dataSource == null) {
throw new ServiceException(Status.RESOURCE_NOT_EXIST);
}
if (!canOperatorPermissions(loginUser, new Object[]{dataSource.getId()}, AuthorizationType.DATASOURCE,
DATASOURCE_UPDATE)) {
throw new ServiceException(Status.USER_NO_OPERATION_PERM);
}
// check name can use or not
if (!dataSourceParam.getName().trim().equals(dataSource.getName()) && checkName(dataSourceParam.getName())) {
throw new ServiceException(Status.DATASOURCE_EXIST);
}
if (checkDescriptionLength(dataSourceParam.getNote())) {
throw new ServiceException(Status.DESCRIPTION_TOO_LONG_ERROR);
}
// check password,if the password is not updated, set to the old password.
ConnectionParam connectionParam = DataSourceUtils.buildConnectionParams(dataSourceParam);
String password = connectionParam.getPassword();View on GitHub (pinned to 02eac45a1b)
Solutions
- Re-fetch the datasource list and use a valid id before updating.
- If the datasource was deleted intentionally, recreate it instead of updating.
- Guard automation: GET the datasource first, and create it when the GET returns 404.
Example fix
// before updateDatasource(user, paramWithId42); // id 42 deleted // after if (getDatasource(id42) == null) createDatasource(param); else updateDatasource(user, paramWithId42);
Defensive patterns
Strategy: validation
Validate before calling
DataSource ds = api.getDatasource(id);
if (ds == null) { throw new IllegalStateException("datasource " + id + " does not exist"); } Type guard
boolean exists(DataSource ds) { return ds != null && ds.getId() > 0; } Try / catch
try { api.updateDataSource(user, param); } catch (ServiceException e) { if (e.getCode() == 20004) { /* recreate or refresh id list */ } else throw e; } Prevention
- Resolve datasource ids by name at run time, not hardcoded
- Refresh UI state after deletions
- GET the datasource before PUT
When it happens
Trigger: PUT /datasources/{id} with an id that was deleted or never existed (queryById returns null).
Common situations: Stale UI tab after another user deleted the datasource; hardcoded ids from another environment; cleanup scripts removed the record before the update ran.
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
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/23f3876f02dc63fc.
Report an issue: GitHub.