{"record":{"id":"5e627f8e7bfa05e1","repo":"SonarSource/sonarqube","slug":"source-and-target-profiles-are-equal-s","errorCode":null,"errorMessage":"Source and target profiles are equal: %s","messagePattern":"Source and target profiles are equal: (.+?)","errorType":"http","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"warning","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java","lineNumber":59,"sourceCode":"    QProfileDto to = prepareTarget(dbSession, sourceProfile, toName);\n    backuper.copy(dbSession, sourceProfile, to);\n    return to;\n  }\n\n  private QProfileDto prepareTarget(DbSession dbSession, QProfileDto sourceProfile, String toName) {\n    verify(sourceProfile.getName(), toName);\n    QProfileName toProfileName = new QProfileName(sourceProfile.getLanguage(), toName);\n    QProfileDto toProfile = db.qualityProfileDao().selectByNameAndLanguage(dbSession, toProfileName.getName(), toProfileName.getLanguage());\n    if (toProfile == null) {\n      toProfile = factory.createCustom(dbSession, toProfileName, sourceProfile.getParentKee());\n      dbSession.commit();\n    }\n    return toProfile;\n  }\n\n  private static void verify(String fromProfileName, String toProfileName) {\n    if (fromProfileName.equals(toProfileName)) {\n      throw new IllegalArgumentException(String.format(\"Source and target profiles are equal: %s\", toProfileName));\n    }\n  }\n}\n","sourceCodeStart":41,"sourceCodeEnd":63,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java#L41-L63","documentation":"QProfileCopier.verify throws IllegalArgumentException when the source and target quality profile names are identical, since copying a profile onto itself is a no-op with undefined semantics. It fires early in prepareTarget before any copy work is done.","triggerScenarios":"POST api/qualityprofiles/copy with fromQualityProfile equal to toQualityProfile (same name). Provisioning scripts templating the target name from the source name without overriding it.","commonSituations":"Config templates where the destination variable was left empty and defaulted to the source name; scripted profile duplication loops with an off-by-one name mapping; manual API misuse copying a profile to itself.","solutions":["Provide a distinct toQualityProfile name in the copy request.","Guard the caller: compare names and skip the API call (or no-op intentionally) when they are equal.","Fix the templating/script variable that produced identical source and target names."],"exampleFix":"// before\ncopyProfile(fromName, fromName); // 400: profiles are equal\n// after\nif (!fromName.equals(toName)) {\n  copyProfile(fromName, toName);\n} else {\n  LOG.info(\"skip copy: source equals target\");\n}","handlingStrategy":"validation","validationCode":"if (fromName.equals(toName)) {\n  LOG.info(\"skip profile copy: source and target are identical\");\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  copyProfile(fromName, toName);\n} catch (SonarQubeClientException e) {\n  if (String.valueOf(e.getMessage()).contains(\"Source and target profiles are equal\")) {\n    LOG.warn(\"copy skipped: identical profile names\");\n  } else throw e;\n}","preventionTips":["Validate template variables so the target profile name is never defaulted to the source","Add an assertion in provisioning scripts that from != to","Treat self-copy as an intentional no-op in idempotent pipelines"],"tags":["sonarqube","webapi","quality-profile","copy","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}