0

Why am I getting the error below when the method signature of find_elements() apparently does support RelativeBy? I bypassed this error by not using relativeBy.

Using selenium 4.33.0 and python 3.13.6

    inner_elements = element.find_elements(by, value)
  File "\venv\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 632, in find_elements
    return self._execute(Command.FIND_CHILD_ELEMENTS, {"using": by, "value": value})["value"]
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "\venv\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 574, in _execute
    return self._parent.execute(command, params)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "\venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 445, in execute
    response = self.command_executor.execute(driver_command, params)
  File "\venv\Lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 400, in execute
    data = utils.dump_json(params)
  File "\venv\Lib\site-packages\selenium\webdriver\remote\utils.py", line 23, in dump_json
    return json.dumps(json_struct)
           ~~~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 261, in iterencode
    return _iterencode(o, 0)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
                    f'is not JSON serializable')
TypeError: Object of type RelativeBy is not JSON serializable


I was using a relativeBy value to find an element inside a specific element. so the code was

myRelativeLocator = locate_with(By.CSS_SELECTOR, "div.someclass").below({By.CSS_SELECTOR:"h4.some_label"})
myWebsitePopupWindow.find_elements(myRelativeLocator)

Example code

The following is an example code that reproduce the error

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with


domain = "https://www.lazyvim.org/"
driver = webdriver.Chrome(webdriver.ChromeOptions())
driver.maximize_window()

driver.get(domain)

# sleep to view result for debugging purpose. not required
time.sleep(3)

# i know implicit wait are bad. just for demo code
driver.implicitly_wait(3)

# find the sidebar on left
sidebar_selector = (By.CSS_SELECTOR, "div.sidebar_njMd")
sidebar = driver.find_element(*sidebar_selector)

# find the > button next to configuration side  menu to expand content
config_dropdown_button_selector = locate_with(
    By.CSS_SELECTOR, "button.clean-btn.menu__caret"
).straight_right_of({By.CSS_SELECTOR: 'a[href="configuration"]'})
config_dropdown_button = sidebar.find_element(config_dropdown_button_selector)

# click the > button
config_dropdown_button.click()


# sleep to view the result
time.sleep(4)
driver.quit()

and I get

DevTools listening on ws://127.0.0.1:65184/devtools/browser/da53e6c1-eff4-42fc-bfe8-ff1a6c16902a
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1754809316.366736   18344 voice_transcription.cc:58] Registering VoiceTranscriptionCapability
[28756:25756:0810/150156.584:ERROR:google_apis\gcm\engine\registration_request.cc:291] Registration response error message: DEPRECATED_ENDPOINT
Traceback (most recent call last):
  File "C:\Users\bd080\test_project\issue_demo2.py", line 27, in <module>
    config_dropdown_button = sidebar.find_element(config_dropdown_button_selector)
  File "C:\Users\bd080\test_project\venv\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 603, in find_element
    return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"]
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bd080\test_project\venv\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 574, in _execute
    return self._parent.execute(command, params)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "C:\Users\bd080\test_project\venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 445, in execute
    response = self.command_executor.execute(driver_command, params)
  File "C:\Users\bd080\test_project\venv\Lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 400, in execute
    data = utils.dump_json(params)
  File "C:\Users\bd080\test_project\venv\Lib\site-packages\selenium\webdriver\remote\utils.py", line 23, in dump_json
    return json.dumps(json_struct)
           ~~~~~~~~~~^^^^^^^^^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 261, in iterencode
    return _iterencode(o, 0)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.1776.0_x64__qbz5n2kfra8p0\Lib\json\encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
                    f'is not JSON serializable')
TypeError: Object of type RelativeBy is not JSON serializable
4
  • you didn't show FULL error message so it is hard to say if problem is really in this part of code. You could also create minimal working code (with URL) so we could test it. Commented Aug 9 at 23:53
  • I can't reproduce this problem with similar code. Problem can be in different place. I can get this error when I use something like .below(myRelativeLocator) - and this can mean problem is in different place, and you probably use wrong values Commented Aug 10 at 0:18
  • I added an example code that can be run to reproduce it. Thank you @furas Commented Aug 10 at 9:59
  • when I use driver instead of sidebar then this problem disappears (but result may not be the same). In documentation I don't see any information about this problem but all examples use driver. Maybe it is bug and it needs to send this problem to author(s). At least you can check if someone already send issue for this. Commented Aug 10 at 10:02

2 Answers 2

2

The reason that you get the

TypeError: Object of type RelativeBy is not JSON serializable

is simply because:

  • The Relative Locators (such as locate_with ) method, which is used to construct RelativeBy objects, work with, and is a method of the WebDriver instance (driver), not an element(WebElement) instance that you're using.

  • In you code, sidebar.find_element() expects a normal By locator, not a Relative locator (config_dropdown_button_selector). Passing a relative locator triggers the occured JSON-serialization error.

So, when using relative locator, you should call find_element() method on the driver object.

Here's you code:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with


domain = "https://www.lazyvim.org/"
driver = webdriver.Chrome(webdriver.ChromeOptions())
driver.maximize_window()
driver.get(domain)

# sleep to view result for debugging purpose. not required
time.sleep(3)
# i know implicit wait are bad. just for demo code
driver.implicitly_wait(3)

# find the sidebar on left
sidebar = driver.find_element(By.CSS_SELECTOR, "div.sidebar_njMd")
#-------------------------------------------------------------------------------------
# Use the driver-level relative locator & then position to the right of the anchor
config_dropdown_button = driver.find_element(
    locate_with(By.CSS_SELECTOR, "button.clean-btn.menu__caret").straight_right_of(sidebar.find_element(By.CSS_SELECTOR, 'a[href="/configuration"]'))
)
#-------------------------------------------------------------------------------------
# click the > button
config_dropdown_button.click()

# sleep to view the result
time.sleep(4)
Sign up to request clarification or add additional context in comments.

1 Comment

Been so long since I posted this question, but thank you. However I still don't see why this is the case, when just reading the documentation and function methods. I feel this should have been documented somewhere
1

First of all to click() on the element with text as Configuration and expand the child elements can be easily achieved using PARTIAL_LINK_TEXT as follows:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

driver.get("https://www.lazyvim.org/")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Configuration"))).click()

Using Relative Locators

Still if you want to use the Relative Locators you can locate the element with text as Configuration and next locate the <button> located to it's right using the to_right_of clause and you can use the following locator strategies:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.relative_locator import locate_with

driver.get("https://www.lazyvim.org/")
config = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Configuration")))
config_dropdown_arrow = driver.find_element(locate_with(By.TAG_NAME, "button").to_right_of(config))
config_dropdown_arrow.click()

Browser Snapshot enter image description here


References

You can find a couple of relevent detailed discussions in:

1 Comment

Thank you for your alternative approaches!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.