pinpoint-apm/pinpoint · error · DataIntegrityViolationException
Duplicate service name:
Error message
Duplicate service name:
What it means
After a DuplicateKeyException from the DAO insert, the code re-checks selectServiceByName; if a row with that name already exists, it rethrows as DataIntegrityViolationException("Duplicate service name: ..."). This distinguishes a genuine name conflict from a duplicate-key caused by something else (e.g. UID collision). The method is @Retryable on DuplicateKeyException, so this explicit rethrow also stops pointless retries.
Source
Thrown at service-module/src/main/java/com/navercorp/pinpoint/service/service/ServiceRegistryServiceImpl.java:45
this.serviceRegistryDao = Objects.requireNonNull(serviceRegistryDao, "serviceRegistryDao");
this.serviceUidGenerator = Objects.requireNonNull(serviceUidGenerator, "serviceUidGenerator");
}
@Override
@Transactional(rollbackFor = {Exception.class})
@Retryable(retryFor = DuplicateKeyException.class, maxAttempts = 3)
public Service insertService(String name) {
StringPrecondition.requireHasLength(name, "name");
if (Service.wellKnownService(name) != null) {
throw new IllegalArgumentException("name is well known");
}
int uid = serviceUidGenerator.generate().getUid();
try {
serviceRegistryDao.insertService(uid, name);
} catch (DuplicateKeyException e) {
if (serviceRegistryDao.selectServiceByName(name) != null) {
throw new DataIntegrityViolationException("Duplicate service name: " + name, e);
}
throw e;
}
return new Service(name, uid);
}
@Override
@Transactional(readOnly = true)
public List<String> getServiceNames() {
return serviceRegistryDao.selectServiceNames();
}
@Override
@Transactional(readOnly = true)
public List<Service> getServiceList(int limit) {
List<ServiceEntity> entityList = serviceRegistryDao.selectServiceList(limit);
return toServices(entityList);View on GitHub (pinned to 744c3d3075)
Solutions
- Check existence first with selectServiceByName and reuse/update the existing service instead of inserting.
- Catch DataIntegrityViolationException (or DuplicateKeyException) around insertService and handle the conflict idempotently.
- Use a unique name or adopt a create-or-get pattern.
Example fix
// before
serviceRegistryService.insertService(name);
// after
if (serviceRegistryService.selectServiceByName(name) == null) {
serviceRegistryService.insertService(name);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (serviceRegistryService.selectServiceByName(name) != null) { /* already exists — skip or reuse */ } Try / catch
try { serviceRegistryService.insertService(name); } catch (DataIntegrityViolationException | DuplicateKeyException e) { /* handle existing-name conflict idempotently */ } Prevention
- Check selectServiceByName before insert
- Make provisioning scripts idempotent
- Avoid concurrent duplicate registrations
When it happens
Trigger: Calling insertService with a name that already exists in the service_registry table (unique-name constraint violation on insert).
Common situations: Two concurrent registrations of the same name; re-running a provisioning script that already created the service; retry after a previous partial failure.
Related errors
- already exist. annotationKey:${annotationKey}, exist:${exist
- duplicated ServiceType ${serviceType} / ${duplicated}
- already exist. serviceType:${serviceType}, exist:${exist}
- eventIdentifier cannot be less than 0
- Duplicate ColumnFamily name :
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/9e41da5e4fc9171d.
Report an issue: GitHub.