SeleniumHQ/selenium · error · InvalidSelectorException

Compound class names are not allowed.

Error message

Compound class names are not allowed.

What it means

Raised as InvalidSelectorException by LocatorConverter.convert when a By.CLASS_NAME locator value contains internal whitespace (after stripping leading/trailing whitespace), which CSS class selectors cannot represent. A compound class name like 'btn primary' maps to multiple CSS classes (.btn.primary) and the converter refuses to silently guess the correct transformation.

Source

Thrown at py/selenium/webdriver/remote/locator_converter.py:29

# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from selenium.common.exceptions import InvalidSelectorException
from selenium.webdriver.common.by import By


class LocatorConverter:
    def convert(self, by, value):
        # Default conversion logic
        if by == By.ID:
            return By.CSS_SELECTOR, f'[id="{value}"]'
        elif by == By.CLASS_NAME:
            if value and any(char.isspace() for char in value.strip()):
                raise InvalidSelectorException("Compound class names are not allowed.")
            return By.CSS_SELECTOR, f".{value}"
        elif by == By.NAME:
            return By.CSS_SELECTOR, f'[name="{value}"]'
        return by, value

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Use By.CSS_SELECTOR for compound classes: driver.find_element(By.CSS_SELECTOR, '.btn.primary')
  2. Select a single class from the compound name if only one is needed
  3. Use By.XPATH with contains(@class, 'className') for partial matching

Example fix

// before
driver.find_element(By.CLASS_NAME, 'btn primary')

// after
driver.find_element(By.CSS_SELECTOR, '.btn.primary')
Defensive patterns

Strategy: validation

Validate before calling

by, value = By.CLASS_NAME, 'btn primary'
if by == By.CLASS_NAME and value and any(c.isspace() for c in value.strip()):
    value = '.'.join(f'.{c}' for c in value.split())
    by = By.CSS_SELECTOR
driver.find_element(by, value)

Type guard

def is_compound_class_name(value: str) -> bool:
    return bool(value and any(c.isspace() for c in value.strip()))

Try / catch

from selenium.common.exceptions import InvalidSelectorException
try:
    driver.find_element(By.CLASS_NAME, class_str)
except InvalidSelectorException:
    css = ''.join(f'.{c}' for c in class_str.split())
    driver.find_element(By.CSS_SELECTOR, css)

Prevention

When it happens

Trigger: Calling driver.find_element(By.CLASS_NAME, 'btn primary') or any By.CLASS_NAME value with a space inside. The converter checks value.strip() for any whitespace character and raises if found.

Common situations: Web elements with multiple CSS classes where the developer passes the full class attribute string. Copy-pasting class names from HTML that contain spaces. Using By.CLASS_NAME when By.CSS_SELECTOR is needed.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/c8a0bd0de4abda94. Report an issue: GitHub.