Skip to content

Login fails with RuntimeError: No locator matched — EMAIL_LOCATORS don't match login page #3

Description

@matiapa

Summary

submit_login_form crashes with RuntimeError: No locator matched on <url> while trying to fill the email field on LinkedIn's login page. None of the EMAIL_LOCATORS in linkedin_cli/browser/login.py matched, so resolve_locator (in linkedin_cli/browser/nav.py) exhausted every candidate and raised.

Environment

  • Consumed via OpenOutreach (eracle/OpenOutreach), running make run / python manage.py rundaemon
  • Platform: Linux aarch64 (Raspberry Pi), Python 3.13.5
  • linkedin-agent-cli installed unpinned from PyPI (latest at time of run)

Steps to reproduce

  1. Configure a LinkedIn account in OpenOutreach and run make run.
  2. Daemon opens the browser, navigates to the login page, and calls authenticate().
  3. Crash occurs immediately after "Submitting login form for <email>" is logged.

Full traceback

[INF] Submitting login form for matiglas@hotmail.com
Traceback (most recent call last):
  File "manage.py", line 24, in <module>
    execute_from_command_line(sys.argv)
  File ".../django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File ".../django/core/management/__init__.py", line 437, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ".../django/core/management/base.py", line 420, in run_from_argv
    self.execute(*args, **cmd_options)
  File ".../django/core/management/base.py", line 464, in execute
    output = self.handle(*args, **options)
  File "openoutreach/core/management/commands/rundaemon.py", line 19, in handle
    self._ensure_newsletter(session)
  File "openoutreach/core/management/commands/rundaemon.py", line 98, in _ensure_newsletter
    profile = session.self_profile
  File ".../functools.py", line 1026, in __get__
    val = self.func(instance)
  File "openoutreach/linkedin/browser/session.py", line 66, in self_profile
    profile = discover_self_profile(self)
  File ".../linkedin_cli/setup/self_profile.py", line 19, in discover_self_profile
    session.ensure_browser()
  File "openoutreach/linkedin/browser/session.py", line 49, in ensure_browser
    start_browser_session(session=self)
  File "openoutreach/linkedin/browser/launch.py", line 45, in start_browser_session
    authenticate(session, username=lp.linkedin_username, password=lp.linkedin_password)
  File ".../linkedin_cli/auth.py", line 94, in authenticate
    auth_flow.run(session)
  File ".../linkedin_cli/page_state.py", line 145, in run
    action(session)
  File ".../linkedin_cli/page_state.py", line 85, in wrapper
    fn(session, *args, **kwargs)
  File ".../linkedin_cli/auth.py", line 67, in _from_login
    submit_login_form(session, session.username, session.password)
  File ".../linkedin_cli/browser/login.py", line 121, in submit_login_form
    human_type(resolve_locator(page, EMAIL_LOCATORS), username)
  File ".../linkedin_cli/browser/nav.py", line 81, in resolve_locator
    raise RuntimeError(f"No locator matched on {page.url}")

Suspected root cause

EMAIL_LOCATORS (linkedin_cli/browser/login.py:25-32) relies on English accessible names for its primary matchers:

EMAIL_LOCATORS = [
    lambda p: p.get_by_role("textbox", name="Email or phone"),
    lambda p: p.get_by_label("Email or phone"),
    lambda p: p.locator('input[autocomplete="webauthn"]'),
    lambda p: p.locator('input[name="session_key"]'),
    lambda p: p.locator('input#username'),
    lambda p: p.locator('form input[type="text"]'),
]

If LinkedIn serves the login page in a non-English locale (e.g. Spanish, based on the account's region), get_by_role/get_by_label won't match on the translated label, and apparently none of the CSS fallbacks matched either in this run — suggesting either a locale-driven DOM/attribute change, or LinkedIn served an interstitial/different login variant that none of the fallbacks anticipated.

Two things that would help narrow this down and make the failure more debuggable:

  1. resolve_locator's RuntimeError doesn't capture page HTML/screenshot on failure, so there's no artifact to inspect after the crash — enabling a dump (similar to DUMP_PAGES in nav.py) on locator-resolution failure would make future reports actionable.
  2. If the locale hypothesis is right, the login locators need either a locale-agnostic strategy (e.g. matching on id/name/type attributes only, without relying on translated accessible names) or explicit multi-locale label lists.

I don't have a captured screenshot/HTML from this run, but can attempt to repro with DUMP_PAGES=true if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions