apache/dolphinscheduler · error · UnsupportedOperationException

The EPHEMERAL data: can only be updated by its owner: but

Error message

The EPHEMERAL data:  can only be updated by its owner:  but not: 

What it means

JdbcRegistryDataManager.putJdbcRegistryData enforces that EPHEMERAL data can only be overwritten by the client (clientId) that created it. A put from a different client on a key owned by another live session throws UnsupportedOperationException. This prevents one server instance from hijacking another instance's ephemeral session nodes.

Source

Thrown at dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-jdbc/src/main/java/org/apache/dolphinscheduler/plugin/registry/jdbc/server/JdbcRegistryDataManager.java:187

    @Override
    public void putJdbcRegistryData(Long clientId, String key, String value, DataType dataType) {
        checkNotNull(clientId);
        checkNotNull(key);
        checkNotNull(dataType);

        final Optional<JdbcRegistryDataDTO> jdbcRegistryDataOptional = jdbcRegistryDataRepository.selectByKey(key);

        jdbcRegistryTransactionTemplate.execute(status -> {
            if (jdbcRegistryDataOptional.isPresent()) {
                JdbcRegistryDataDTO jdbcRegistryData = jdbcRegistryDataOptional.get();
                if (!dataType.name().equals(jdbcRegistryData.getDataType())) {
                    throw new UnsupportedOperationException("The data type: " + jdbcRegistryData.getDataType()
                            + " of the key: " + key + " cannot be updated");
                }

                if (DataType.EPHEMERAL.name().equals(jdbcRegistryData.getDataType())) {
                    if (!jdbcRegistryData.getClientId().equals(clientId)) {
                        throw new UnsupportedOperationException(
                                "The EPHEMERAL data: " + key + " can only be updated by its owner: "
                                        + jdbcRegistryData.getClientId() + " but not: " + clientId);
                    }
                }

                jdbcRegistryData.setDataValue(value);
                jdbcRegistryData.setLastUpdateTime(new Date());
                jdbcRegistryDataRepository.updateById(jdbcRegistryData);

                JdbcRegistryDataChangeEventDTO jdbcRegistryDataChangeEvent = JdbcRegistryDataChangeEventDTO.builder()
                        .jdbcRegistryData(jdbcRegistryData)
                        .eventType(JdbcRegistryDataChangeEventDTO.EventType.UPDATE)
                        .createTime(new Date())
                        .build();
                jdbcRegistryDataChangeEventRepository.insert(jdbcRegistryDataChangeEvent);
            } else {
                JdbcRegistryDataDTO jdbcRegistryDataDTO = JdbcRegistryDataDTO.builder()
                        .clientId(clientId)

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Use unique per-client key paths (include clientId/host) for ephemeral data
  2. Wait for the old owner's session to expire or delete the key with the owner client before rewriting
  3. Use PERSISTENT data instead if multiple clients must write the same key

Example fix

// before
registryClient.put("/nodes/master/lock", value, DataType.EPHEMERAL); // written by all instances
// after
String ownedKey = "/nodes/master/lock/" + clientId;
registryClient.put(ownedKey, value, DataType.EPHEMERAL);
Defensive patterns

Strategy: try-catch

Validate before calling

JdbcRegistryDataDTO d = repository.selectByKey(key).orElse(null); if (d != null && DataType.EPHEMERAL.name().equals(d.getDataType()) && !d.getClientId().equals(myClientId)) { skipWrite(key); }

Try / catch

try { manager.putJdbcRegistryData(key, value, DataType.EPHEMERAL, clientId); } catch (UnsupportedOperationException e) { log.error("Not owner of ephemeral {}: {}", key, e.getMessage()); }

Prevention

When it happens

Trigger: Client A calling put on a key whose jdbcRegistryData.clientId is client B; multiple DolphinScheduler servers writing the same ephemeral key (e.g. a task or master ephemeral path) concurrently; a restarted instance reusing a key path still owned by its dead-but-unexpired previous clientId.

Common situations: Key still exists from a crashed instance because its session hasn't timed out, misconfigured identical ephemeral paths across instances, load-distributed writers assuming shared ownership of ephemeral keys.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/fb5fef2719a90eaa. Report an issue: GitHub.