HKUDS/DeepTutor · error · ValueError

Capability not found: {resolved}

Error message

Capability not found: {resolved}

What it means

A defensive invariant in `get_capability_contract`: after `resolve_capability` returned a canonical name, no manifest with that `name` was found in the registry. Normally unreachable (resolve checks the same manifests), so hitting it means the registry mutated between the two calls or manifests are inconsistent.

Source

Thrown at deeptutor/app/facade.py:96

        contracts = []
        for manifest in self.capabilities.get_manifests():
            contracts.append(
                {
                    **manifest,
                    "availability": self.get_capability_availability(manifest["name"]).__dict__,
                }
            )
        return contracts

    def get_capability_contract(self, value: str) -> dict[str, Any]:
        resolved = self.resolve_capability(value)
        for manifest in self.capabilities.get_manifests():
            if manifest["name"] == resolved:
                return {
                    **manifest,
                    "availability": self.get_capability_availability(resolved).__dict__,
                }
        raise ValueError(f"Capability not found: {resolved}")

    def get_capability_availability(self, capability: str) -> CapabilityAvailability:
        resolved = self.resolve_capability(capability)
        if resolved == "math_animator":
            available = importlib.util.find_spec("manim") is not None
            return CapabilityAvailability(
                name=resolved,
                available=available,
                install_hint=(
                    ""
                    if available
                    else "Install with `pip install -e '.[math-animator]'` "
                    "or `pip install -r requirements/math-animator.txt`."
                ),
            )
        return CapabilityAvailability(name=resolved, available=True)

    async def start_turn(

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Retry the call — the registry may have been mid-mutation
  2. Audit for concurrent registration/unregistration and serialize registry access
  3. If using a custom ToolRegistry/CapabilityRegistry, ensure get_manifests() is consistent with resolution lookups
Defensive patterns

Strategy: retry

Validate before calling

contracts = {c["name"] for c in app.get_capability_contracts()}
if name not in contracts:
    # registry in flux or stale; refresh/retry registration
    ...

Try / catch

for attempt in range(3):
    try:
        return app.get_capability_contract(name)
    except ValueError:
        time.sleep(0.2 * (attempt + 1))
raise

Prevention

When it happens

Trigger: Calling `app.get_capability_contract(name)` while another thread/task unregisters or reloads capabilities between `resolve_capability` and the manifest loop; or a registry implementation whose `get_manifests()` returns a filtered/different set than the one used for resolution.

Common situations: Concurrent capability hot-reload during a WebSocket turn; a custom registry subclass that filters manifests inconsistently; monkeypatched manifests in tests.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/f7090bb8e2edfd23. Report an issue: GitHub.