can1357/oh-my-pi · error · ToolError
Async job manager unavailable for this session.
Error message
Async job manager unavailable for this session.
What it means
When the caller explicitly requests async=true, the tool requires session.asyncJobManager to register the background job, deliver progress, and support later job-control calls. If the manager is absent the request cannot be honored and the tool throws immediately, before #startManagedBashJob runs. This is the explicit-async counterpart of the same guard inside #startManagedBashJob.
Source
Thrown at packages/coding-agent/src/tools/bash.ts:1013
throw new ToolError(`Working directory is not a directory: ${commandCwd}`);
}
// A timeout of 0 is an explicit long-running-command contract: the user
// must still cancel the call or job, but OMP does not impose a deadline.
const requestedTimeoutSec = rawTimeout;
const timeoutDisabled = requestedTimeoutSec === 0;
const maxTimeout = this.session.settings.get("tools.maxTimeout");
const timeoutSec = timeoutDisabled ? undefined : clampTimeout("bash", requestedTimeoutSec, maxTimeout);
const timeoutMs = timeoutSec === undefined ? undefined : timeoutSec * 1000;
const pendingNotices: string[] = [];
if (timeoutSec !== undefined) {
const timeoutClampNotice = formatTimeoutClampNotice(requestedTimeoutSec, timeoutSec, maxTimeout);
if (timeoutClampNotice) pendingNotices.push(timeoutClampNotice);
}
if (asyncRequested) {
if (!this.session.asyncJobManager) {
throw new ToolError("Async job manager unavailable for this session.");
}
const job = this.#startManagedBashJob({
command,
commandCwd,
timeoutMs,
timeoutSec,
requestedTimeoutSec,
notices: pendingNotices,
resolvedEnv,
onUpdate,
forwardUpdates: false,
});
return this.#buildBackgroundStartResult(job.jobId, "", timeoutSec, {
requestedTimeoutSec,
notices: pendingNotices,
});
}View on GitHub (pinned to 9690622007)
Solutions
- Attach an AsyncJobManager to the session (session.asyncJobManager = new AsyncJobManager()) before making async bash calls.
- Run the command synchronously (omit async) if the host cannot support job management.
- Gate the feature in your embedding layer: check session.asyncJobManager first and disable background prompts when it's missing.
Example fix
// before: stub session missing the manager
const session = baseSession; // asyncJobManager: undefined
await bash.execute(id, { command: "make all", async: true });
// after: supply the manager or run foreground
session.asyncJobManager = new AsyncJobManager();
await bash.execute(id, { command: "make all", async: true }); Defensive patterns
Strategy: validation
Validate before calling
if (asyncRequested && !session.asyncJobManager) {
asyncRequested = false; // degrade to foreground, or surface a config error
}
await bash.execute(id, { command, async: asyncRequested }); Try / catch
try {
await bash.execute(id, { command, async: true });
} catch (e) {
if (e instanceof ToolError && e.message.includes("job manager unavailable")) {
return bash.execute(id, { command });
}
throw e;
} Prevention
- Wire AsyncJobManager into every session your host creates.
- Feature-detect session.asyncJobManager before exposing async bash to the model.
- Cover session construction in tests so the manager is never silently missing.
When it happens
Trigger: bash tool call with async=true on a session whose asyncJobManager was never attached (minimal SDK session, alternative host, or a session type without background-job support).
Common situations: Embedding the coding agent in an app with a hand-rolled session object; running the tool against a session created by an older integration layer; test harnesses stubbing the session incompletely.
Related errors
- Background job manager unavailable for this session.
- operation canceled
- aborted
- xd:// is not mounted in this session.
- Unknown security operation: ${operationId}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/23e5cfc50b184dbf.
Report an issue: GitHub.