JuliusBrussee/caveman · warning · AsyncJobsUnavailableError
cave_async_jobs_unavailable
cave_async_jobs_unavailable
Error message
Async job execution is unavailable: durable encrypted request storage, provider credential custody, and a draining worker are not wired. No job was submitted.
What it means
`_AsyncJobs.submit()` is intentionally not implemented: the backend prerequisites (durable encrypted request storage, provider credential custody, and a draining worker) are not wired, so the method unconditionally raises `AsyncJobsUnavailableError` (code `cave_async_jobs_unavailable`). No network request is made and no job is ever created.
Solutions
- Use the synchronous request path (`client.request(...)` or the equivalent completion call) instead of submitting a background job.
- Implement your own queue (e.g. persist requests and process them in a worker you control) until async jobs ship.
- Check for an SDK/gateway update that wires async jobs, and feature-detect before relying on it.
- Catch `AsyncJobsUnavailableError` and fall back to synchronous execution with your own retry policy.
Example fix
// before
job = client.async_jobs.submit(body)
// after
try:
job = client.async_jobs.submit(body)
except AsyncJobsUnavailableError:
result = client.request(body) # synchronous fallback Defensive patterns
Strategy: try-catch
Validate before calling
if isinstance(client.async_jobs.submit, type(lambda *a, **k: (_ for _ in ()).throw(AsyncJobsUnavailableError()))):
pass # simpler: wrap the call and catch — the feature is version-gated, not detectable upfront Type guard
def async_jobs_available(client) -> bool:
try:
client.async_jobs.submit({})
except AsyncJobsUnavailableError:
return False
except Exception:
return True # reachable endpoint means feature exists
return True Try / catch
try:
job = client.async_jobs.submit(body, latency_class="background")
except AsyncJobsUnavailableError:
log.warning("async jobs unavailable; running synchronously")
result = client.request(body) Prevention
- Feature-detect or version-gate async job usage behind a config flag.
- Never assume background submission exists; design the pipeline to work synchronously.
- Check release notes when upgrading the SDK before enabling async paths.
When it happens
Trigger: Calling `client.async_jobs.submit(body, latency_class="background")` (any arguments) on any deployment of this SDK version.
Common situations: Migrating a batch pipeline that assumed async submission exists, or following documentation for a newer/other SDK release where async jobs are available.
Related errors
- cave_async_jobs_unavailable
- Caveman delegates through public chat_with_tools methods
- Agno middleware requires a nonempty native session_id
- Agno scope resolver must return a Caveman Scope
- artifact_id is required
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/047797a975d818d4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/sdk/python/caveman_cloud/core.py:1451
super().__init__(
"Async job execution is unavailable: durable encrypted request storage, "
"provider credential custody, and a draining worker are not wired. No job was submitted."
)
class JobsClient:
"""Reserved async-job surface that fails locally before network I/O."""
def __init__(self, cave: Cave) -> None:
self.cave = cave
def submit(
self,
body: dict[str, Any],
*,
latency_class: str = "background",
) -> Job:
raise AsyncJobsUnavailableError
def status(self, job_id: str) -> Job:
raise AsyncJobsUnavailableError
def cancel(self, job_id: str) -> dict[str, Any]:
raise AsyncJobsUnavailableError
def wait(
self,
job_id: str,
*,
interval_s: float = 0.5,
timeout_s: float = 60.0,
) -> Job:
raise AsyncJobsUnavailableError
def submit_and_wait(
self,View on GitHub (pinned to 3ee70a1026)