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

  1. Re-fetch the datasource list and use a valid id before updating.
  2. If the datasource was deleted intentionally, recreate it instead of updating.
  3. 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

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.