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.
| Error | Meaning | Fast 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)
- Detect:
await RTOForm.detect(1500). If this fails, fix extension install/loading first. - Allow-list: confirm the host is allowed (or add it).
- Controlled tab:
await RTOForm.openTab({ tabKey, url }, { timeoutMs: 20000 }). - Confirm tabKey exists:
await RTOForm.listTabs()(orRTOTabsList.requestNow()). - Selectors:
waitForSelectorbefore any DOM action; remember top-frame only. - 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).