JuliusBrussee/caveman · error · TypeError
LlamaIndex scope resolver must return a Caveman Scope
Error message
LlamaIndex scope resolver must return a Caveman Scope
What it means
_scope accepts either a Scope instance or a resolver callable invoked with the workflow Context; it then validates the result. If the callable returns anything that is not a caveman_cloud.middleware.Scope (None, dict, str, framework object), it raises TypeError — recovery and tool gating need a real Scope to attribute calls.
Solutions
- Make the resolver return caveman_cloud.middleware.Scope(...) in every branch, including error/empty paths
- If a miss is possible, raise or substitute a default Scope instead of returning None
- Convert framework context data into a Scope explicitly before returning it
- Check for duplicate caveman-cloud versions (pip show caveman-cloud) so isinstance matches one class
Example fix
// before
def resolve(ctx):
return ctx.store.get("session") # may be a dict or None
// after
from caveman_cloud.middleware import Scope
def resolve(ctx):
session = ctx.store.get("session")
return Scope(subject=session["user"], call_type="agent_step") if session else Scope.anonymous() Defensive patterns
Strategy: type-guard
Validate before calling
result = resolver(context) if not isinstance(resolver, Scope) else resolver
if not isinstance(result, Scope):
raise TypeError("scope resolver must return caveman_cloud.middleware.Scope") Type guard
def resolves_to_scope(resolver, context=None) -> bool:
from caveman_cloud.middleware import Scope
candidate = resolver if isinstance(resolver, Scope) else resolver(context)
return isinstance(candidate, Scope) Try / catch
try:
scope = adapter_step(scope_resolver, context)
except TypeError as e:
if "must return a Caveman Scope" in str(e):
scope = default_scope() # construct a valid Scope and continue/degrade Prevention
- Have resolvers return a Scope in every branch; never return None on misses
- Convert dicts/user claims into Scope explicitly at the resolver boundary
- Unit-test resolvers asserting isinstance(result, Scope)
- Keep one caveman-cloud version installed so the Scope class identity matches
When it happens
Trigger: Passing a scope resolver function whose return value is not a Scope — e.g. returning None on a cache miss, returning a dict of user claims, or returning a string session id — to recover/arecover/_options/take_step or the reader path.
Common situations: Resolver written before the Scope class existed and returning legacy dict context; early-return None when workflow context is empty; returning result.value or context metadata instead of a constructed Scope; duplicate caveman-cloud installs causing a different Scope class.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Agno scope resolver must return a Caveman Scope
- AutoGen requires a stable Caveman Scope for each agent or…
- Expected a native Strands Model
- Expected a native ToolSelection
- Expected an AutoGen ChatCompletionClient
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/065bab14e89d5495.
Report an issue: GitHub.
Appendix: source
Thrown at packages/middleware/python/caveman_middleware/llama_index.py:46
from caveman_cloud.middleware import Adapter, Candidate, MiddlewareError, MiddlewareRuntime, RecoveryBinding, Scope
from caveman_cloud.middleware.runtime import RECOVERY_DESCRIPTION, RECOVERY_SCHEMA
from ._native import Attempt, manifest, owner
from ._usage import usage
from ._versions import matches_framework, supports_framework
ADAPTER = Adapter("llama-index", "0.1.0", "0.14.24", "llama-index-message-v1")
RAG_ADAPTER = Adapter("llama-index-rag", "0.1.0", "0.14.24", "llama-index-node-v1")
def _check_version(runtime):
return supports_framework(runtime, ("llama-index-core", "0.14", "0.15"))
def _scope(source, context=None):
result = source if isinstance(source, Scope) else source(context)
if not isinstance(result, Scope):
raise TypeError("LlamaIndex scope resolver must return a Caveman Scope")
return result
def _async_runtime(runtime):
return runtime.as_async() if isinstance(runtime, MiddlewareRuntime) else runtime
def _protocol(model, runtime):
provider = (type(model).__module__, type(model).__name__)
supported = {
("llama_index.llms.openai.base", "OpenAI"): ("llama-index-llms-openai", "0.8", "1", "openai-chat"),
("llama_index.llms.anthropic.base", "Anthropic"): ("llama-index-llms-anthropic", "0.12", "1", "anthropic-messages"),
}
match = supported.get(provider)
if match and not supports_framework(runtime, match[:3]):
return None
if match:
sdk = ("openai", "2.54", "4") if match[3] == "openai-chat" else ("anthropic", "0.125", "2")View on GitHub (pinned to 3ee70a1026)