SonarSource/sonarqube · error · BadRequestException

' ' contains the invalid character ' '. Azure DevOps names…

Error message

'%s' contains the invalid character '%s'. Azure DevOps names must not contain any of: \ / : < > | ? *

What it means

AlmSettingsSupport.validateAzureName checks that Azure DevOps name fields (project, repository, etc.) contain none of the characters \ / : < > | ? *, which Azure DevOps forbids. On violation it logs a warning and throws BadRequestException naming the field and the offending character.

Solutions

  1. Remove the reported invalid character from the field value named in the message
  2. Use the Azure DevOps project/repository display name, not a path with slashes
  3. Sanitize user-supplied names in automation before calling the API
  4. Rename the project/repo in Azure DevOps if its actual name contains forbidden characters

Example fix

// before
almSettings.updateAzure("ado", "TeamProject/SubProject");
// after
almSettings.updateAzure("ado", "TeamProject SubProject");
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern INVALID = Pattern.compile("[\\\\/:<>|?*]");
void assertValidAzureName(String v) { Matcher m = INVALID.matcher(v); if (m.find()) throw new IllegalArgumentException("contains invalid character " + m.group()); }

Type guard

boolean isValidAzureName(String v) { return v != null && !Pattern.compile("[\\\\/:<>|?*]").matcher(v).find(); }

Try / catch

try { support.validateAzureName("project", name); } catch (BadRequestException e) { sanitizeNameAndRetry(); }

Prevention

When it happens

Trigger: Creating/updating an Azure DevOps ALM setting where the field value passed to validateAzureName contains a forbidden character; the matcher finds the first invalid char and it is embedded in the 400 message.

Common situations: Azure project names containing slashes or spaces-separated paths; automation copying full repo paths ('repo/subdir') into the repository field; names with special characters from templating systems.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/69f1f7722aba9adb. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/AlmSettingsSupport.java:145

    }
  }

  public void validateUrl(@Nullable String url) {
    if (url == null || HttpUrl.parse(url) == null) {
      LOG.warn("Rejected an invalid DevOps Platform URL");
      throw BadRequestException.create(format("Invalid URL: '%s'.", url));
    }
  }

  public void validateAzureName(String fieldName, String value) {
    Matcher matcher = AZURE_NAME_INVALID_CHARS.matcher(value);
    if (matcher.find()) {
      String invalidChar = matcher.group();
      if (LOG.isWarnEnabled()) {
        LOG.warn("Rejected Azure DevOps name for field '{}': contains invalid character '{}'", fieldName, invalidChar);
      }
      throw BadRequestException.create(format(
        "'%s' contains the invalid character '%s'. Azure DevOps names must not contain any of: \\ / : < > | ? *",
        fieldName, invalidChar));
    }
  }

  public ProjectDto getProjectAsAdmin(DbSession dbSession, String projectKey) {
    return getProject(dbSession, projectKey, ADMIN);
  }

  public ProjectDto getProject(DbSession dbSession, String projectKey, ProjectPermission projectPermission) {
    ProjectDto project = componentFinder.getProjectByKey(dbSession, projectKey);
    userSession.checkEntityPermission(projectPermission, project);
    return project;
  }

  public record NewAzureSetting(String key, String url, String personalAccessToken) {
  }

  public record NewGitlabSetting(String key, String url, String personalAccessToken) {

View on GitHub (pinned to 184c821202)