affaan-m/ECC · error · TimeoutError

Condition not met within {timeout}s

Error message

Condition not met within {timeout}s

What it means

A TimeoutError raised by wait_until() in a Windows desktop UI automation helper when a polled condition fn() never returns truthy within the timeout window. wait_until is the fallback path used when UIA events are unreliable. It polls every `interval` seconds until `timeout` elapses, swallowing per-iteration exceptions.

Source

Thrown at skills/windows-desktop-e2e/SKILL.md:175

        return spec

    def wait_window(self, title, timeout=ACTION_TIMEOUT):
        """Wait for a new top-level window (dialogs, child windows)."""
        dlg = Desktop(backend="uia").window(title=title)
        dlg.wait("visible", timeout=timeout)
        return dlg

    def wait_until(self, fn, timeout=ACTION_TIMEOUT, interval=0.3):
        """Poll an arbitrary condition — use when UIA events are unreliable."""
        deadline = time.time() + timeout
        while time.time() < deadline:
            try:
                if fn():
                    return True
            except Exception:
                pass
            time.sleep(interval)
        raise TimeoutError(f"Condition not met within {timeout}s")

    # --- Actions ---

    def click(self, spec):
        self.wait_visible(spec)
        spec.click_input()

    def type_text(self, spec, text):
        self.wait_visible(spec)
        ctrl = spec.wrapper_object()
        try:
            ctrl.set_edit_text(text)
        except Exception as e:
            # Qt 5.x fallback: UIA Value Pattern may be incomplete
            import sys, pywinauto.keyboard as kb
            print(f"[windows-desktop-e2e] set_edit_text failed ({e}), using keyboard fallback", file=sys.stderr)
            ctrl.click_input()
            kb.send_keys("^a")

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Increase timeout only after confirming the control is reachable; first capture a screenshot at failure time to see the real UI state.
  2. Verify the spec/selector still matches the current build of the app under test.
  3. Make sure the test session is interactive (not locked) and the app window is foregrounded before polling.
  4. Replace blind polling with a UIA event listener where possible; wait_until is explicitly the fallback for when events are unreliable.
  5. Log the last exception swallowed inside the loop so silent failures during polling are diagnosable.

Example fix

# before
while time.time() < deadline:
    try:
        if fn():
            return True
    except Exception:
        pass
    time.sleep(interval)
raise TimeoutError(f"Condition not met within {timeout}s")

# after: capture the last error for diagnosis
last_err = None
while time.time() < deadline:
    try:
        if fn():
            return True
    except Exception as e:
        last_err = e
    time.sleep(interval)
raise TimeoutError(f"Condition not met within {timeout}s; last error: {last_err}")
Defensive patterns

Strategy: retry

Validate before calling

def condition_likely_reachable(spec) -> bool:
    # precondition: window is foreground and control exists in the tree
    try:
        return app.top_window().exists() and spec.exists(timeout=1)
    except Exception:
        return False

if not condition_likely_reachable(spec):
    raise RuntimeError("target window/control not present; aborting before wait_until")

Type guard

null

Try / catch

try:
    helper.wait_until(lambda: spec.exists(), timeout=30)
except TimeoutError as e:
    screenshot("artifacts/wait_timeout.png")
    raise AssertionError(f"{e}; see artifacts/wait_timeout.png") from e

Prevention

When it happens

Trigger: Calling wait_until(fn, timeout, interval) where fn() keeps returning False, or keeps raising exceptions, for the full timeout. Common when the target control never appears, the wrong window is focused, or the automation selector does not match the rendered UI.

Common situations: UI changed between recordings so the selector no longer resolves; the app is slow to render under CI load; a modal blocked the target; the test machine is locked/screensaver-on so UIA returns nothing; DPI scaling mismatch hid the control.

Understand the failure class

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/cf0d53fcb47c8192. Report an issue: GitHub.