Skip to content

fix(youtube): login detection, watch-history selector drift, error envelope#79

Open
volod-vana wants to merge 2 commits into
mainfrom
volod/youtube-login-detect-fix
Open

fix(youtube): login detection, watch-history selector drift, error envelope#79
volod-vana wants to merge 2 commits into
mainfrom
volod/youtube-login-detect-fix

Conversation

@volod-vana

@volod-vana volod-vana commented Jun 1, 2026

Copy link
Copy Markdown
Member

Three connector bugs found while wiring YouTube into Memory, all in connectors/google/youtube-playwright.js. First two were diagnosed from the actual DataConnect.log; the third was confirmed live against youtube.com/feed/history in a logged-in browser.

1. Login-detection race (blocked connecting at all)

After the headed-browser login + goHeadless({ resumeUrl }), the connector judged login on the first frame via settleLoggedInSession() — before YouTube's SPA re-rendered the avatar — so a successful manual login read as "not logged in." The programmatic path retried; the headed fallback checked once.

  • settleLoggedInSession() now waits for the topbar to render a decisive element (avatar or sign-in link) before judging.
  • The headed path retries (mirrors the programmatic path).

e2e validated — connect now completes: 20 subscriptions, 100 likes, 5 watch laterclassified outcome: success.

2. Error envelope missing timestamp

The login-failure return was { error } with no timestamp, so Data Connect rejected it as "Protocol violation: timestamp is required" instead of a clean "Login failed." Both error returns now include success: false + timestamp.

3. Watch-history scraping returned 0 (selector drift)

Even with watch history on, history came back empty. Inspected the live page: the yt-lockup-view-model items exist, but every inner selector the extractor used had drifted (YouTube now obfuscates those class names), so linkEl was null → continue skipped every item → 0 results.

Old (dead) New (stable, validated live 7/7)
content-id-{id} class videoId parsed from a[href*="/watch"] ?v= (class fallback kept)
a.yt-lockup-view-model__content-image a[href*="/watch"]
h3.yt-lockup-...__heading-reset h3[title] / h3 text
header #header #title ytd-item-section-header-renderer h2
channel [aria-label^="Go to channel"] unchanged (only selector that survived)

Follows the connector skill guidance: structural selectors / ARIA, never obfuscated class names.

Versioning / testing

…-formed error envelope

Connecting YouTube failed even after a successful manual login. Two bugs:

1. Login-detection race. After the headed-browser login + goHeadless resume, the
   connector judged login status on the FIRST frame via settleLoggedInSession,
   before YouTube's SPA re-rendered the signed-in avatar — so a successful login
   read as 'not logged in'. The programmatic path already retried; the headed
   fallback did not.
   - settleLoggedInSession now waits for the topbar to render a decisive element
     (avatar OR sign-in link) before judging.
   - The headed path retries (mirrors the programmatic path) instead of a single
     first-frame check.

2. Error envelope missing timestamp. The login-failure return was { error } with
   no timestamp, so DataConnect classified it as 'Protocol violation: timestamp
   is required' instead of a clean login failure. Both error returns now include
   success:false + timestamp.

Bump connector + registry to 1.0.1; refresh checksums.

Validated structurally (node -c; validate-connector.cjs 41 passed / 0 failed).
NOT verified against a live Google login — needs a real run.
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Schema Health Check — Non-blocking inherited issues

41/47 scopes consistent | 6 inherited Gateway gap(s) | no new blocking issues in this PR

The history scrape returned 0 items even with watch history ON. Confirmed live
on youtube.com/feed/history: the lockups exist (yt-lockup-view-model), but every
INNER selector the extractor relied on had drifted and YouTube now obfuscates
those class names:
  - content-id-{videoId} class           -> gone (videoId now only in the href)
  - a.yt-lockup-view-model__content-image -> gone
  - a.yt-lockup-metadata-view-model__title -> gone
  - h3.yt-lockup-metadata-view-model__heading-reset -> gone
So linkEl was null -> 'continue' skipped every item -> 0 results.

Rewrote extraction with STABLE structural selectors (validated live, 7/7 items):
  - link:    a[href*='/watch']  (videoId parsed from ?v=, content-id-* fallback)
  - title:   h3[title] / h3 text
  - channel: [aria-label^='Go to channel']  (the one selector that survived)
  - header:  ytd-item-section-header-renderer h2  (Today / Yesterday / date)
  - views:   metadata span matching /views/

Refresh registry script checksum.
@volod-vana volod-vana changed the title fix(youtube): detect manual login + well-formed error envelope fix(youtube): login detection, watch-history selector drift, error envelope Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant