Errors & troubleshooting

Quick fixes for the most common setup and automation problems.
Docs updated: 2026-03-24

Common errors

Important
Errors may come from 3 places: page helpers (JS in your site), background (extension service worker), or content script (running inside the controlled tab). The same label like TIMEOUT can happen at different layers.
ErrorMeaningFast fix
EXT_NOT_DETECTED The page-side helper cannot detect the extension / no response to detect. Install/enable the extension. Then run await RTOForm.detect(1500). Ensure RTO_form_api.js is loaded before your code.
BACKGROUND_NO_RESPONSE The content script tried to talk to background but got no reply (MV3 suspended/reloaded, or extension restart). Retry once. If it persists, reload the extension and the controlled tab, then re-run detect + openTab.
DOMAIN_NOT_ALLOWED The host is not allow-listed (core safety boundary). Request the host (see Allow-list), approve it on the master tab, then retry the action.
NO_CONTROLLED_TAB No controlled tab exists for the tabKey you used. Call openTab({ tabKey, url }) first (or adoptTab). Verify you pass the same tabKey everywhere.
TAB_NOT_FOUND The tabKey does not match any currently controlled tab (stale key / released / closed). Call listTabs() (or RTOTabsList.requestNow()) to see active keys and re-open if needed.
TIMEOUT No response was received in time (slow page, blocked content script, or listTabs postMessage timeout). Increase timeoutMs, and for DOM actions use waitForSelector before interacting. For approval flows, allow enough time for the user to confirm on the master tab.
ELEMENT_NOT_FOUND The selector did not match any element in the controlled tab (at the moment of execution). Use a stable selector and do waitForSelector. Remember: DOM actions run top-frame only (iframes won’t match).
PROTECTED_ELEMENT The element exists but is inside the extension’s protected UI area (blocked by design). Pick a selector that targets the page content, not extension-injected nodes (e.g. avoid things under #rtom-ctrl-host / banners).
INVALID_PAYLOAD Missing/invalid payload fields for an action (example: getAttr without name). Check you pass required fields. For DOM commands: typically { tabKey, selector } + action-specific fields.
UNKNOWN_ACTION A DOM command action name was not recognized by the content script. Check spelling. Confirm your helper/docs match the extension version. Use only the canonical action names in dom.php.
OPTION_NOT_FOUND selectOption could not find the requested option (value/label/index mismatch). Inspect the target <select> options and use a matching value or correct label/index.
NO_ROOT domExtractBlock could not determine a root node (rare, page edge case). Pass an explicit root selector in the payload or use rootStrategy.
INVALID_URL A URL was missing/malformed (tab methods like openTab/navigate). Use a full URL: https://example.com/path.
INVALID_HOST A host value is missing/malformed (allow-list operations). Provide only a host/pattern (example: example.com or *.google.*), not a full URL.
RATE_LIMIT_ALLOWLIST Too many allow-list add requests were sent in a short time from the same page. Wait a moment, avoid double clicks, then retry one clean request.
TOO_MANY_PENDING_REQUESTS The extension already has too many guarded requests waiting. Let the current requests finish, then retry. If your page has buttons, keep one click per action and wait for the visible result.
USER_CANCELLED The user rejected the action or declined the allow-list request on the master tab. This is not a crash. Keep the UI calm, show a friendly “cancelled” message, and let the user retry manually if needed.
Allow-list refusal or cancel
If the user rejects the request, or does not approve it on the master tab, the page-side add flow does not become a silent success. Expect a failed result or a “not added” UI message, then let the user retry explicitly.

Debug steps (fast)

  1. Detect: await RTOForm.detect(1500). If this fails, fix extension install/loading first.
  2. Allow-list: confirm the host is allowed (or add it).
  3. Controlled tab: await RTOForm.openTab({ tabKey, url }, { timeoutMs: 20000 }).
  4. Confirm tabKey exists: await RTOForm.listTabs() (or RTOTabsList.requestNow()).
  5. Selectors: waitForSelector before any DOM action; remember top-frame only.
  6. MV3 weirdness: if you see BACKGROUND_NO_RESPONSE, retry once, otherwise reload tab/extension.

Copy/paste debug snippets

(async function(){
  try{
    await RTOForm.detect(1500);
    console.log("✅ detected");

    const tabs = await RTOForm.listTabs({}, { timeoutMs: 4000 });
    console.log("tabs:", tabs);

    // Optional: quick DOM probe (replace tabKey + selector)
    // await RTOForm.waitForSelector({ tabKey:"demo", selector:"#login" }, { timeoutMs: 8000 });
    // const t = await RTOForm.getText({ tabKey:"demo", selector:"#login" }, { timeoutMs: 8000 });
    // console.log("text:", t);
  }catch(e){
    console.error("RTO debug error:", e);
  }
})();
Tip
If a selector works in DevTools but fails in RTO, it’s often because the element is inside an iframe (RTO runs top-frame only) or it appears after a SPA update (use waitForSelector with a bigger timeout).

Next