can1357/oh-my-pi · error · StructuredSubagentError
Cannot spawn '${agentName}'. Allowed: ${spawnPolicy.allowedE
Error message
Cannot spawn '${agentName}'. Allowed: ${spawnPolicy.allowedErrorText} What it means
Thrown in preflight when session spawn policy disallows the requested agent. `resolveSpawnPolicy(request.session.getSessionSpawns())` yields an allowlist (`allowedAgents`) and enabled flag; if spawns are disabled or the agent is not on the allowlist, the error lists the permitted agents via `allowedErrorText`.
Source
Thrown at packages/coding-agent/src/task/structured-subagent.ts:233
function assertDepthAndSpawnAllowed(request: StructuredSubagentRequest, agentName: string): void {
const taskDepth = request.session.taskDepth ?? 0;
const maxDepth = request.session.settings.get("task.maxRecursionDepth") ?? 2;
if (!canSpawnAtDepth(maxDepth, taskDepth)) {
throw new StructuredSubagentError(
"preflight",
`Cannot spawn another agent at task depth ${taskDepth}; maximum depth is ${maxDepth}.`,
);
}
const blockedAgent = request.blockedAgent ?? $env.PI_BLOCKED_AGENT;
if (blockedAgent && blockedAgent === agentName) {
throw new StructuredSubagentError(
"preflight",
`Cannot spawn ${blockedAgent} agent from within itself (recursion prevention). Use a different agent type.`,
);
}
const spawnPolicy = resolveSpawnPolicy(request.session.getSessionSpawns());
if (!spawnPolicy.enabled || (spawnPolicy.allowedAgents !== null && !spawnPolicy.allowedAgents.includes(agentName))) {
throw new StructuredSubagentError(
"preflight",
`Cannot spawn '${agentName}'. Allowed: ${spawnPolicy.allowedErrorText}`,
);
}
}
/**
* Resolve every policy shared by task and eval before allocating artifacts or
* dispatching work. Callers translate {@link StructuredSubagentError} into
* their own wire-level error surface.
*/
export async function resolveEffectiveSubagentPolicy(
request: StructuredSubagentRequest,
): Promise<EffectiveSubagentPolicy> {
await request.session.settings.reloadFromDisk();
const spawnPolicy = resolveSpawnPolicy(request.session.getSessionSpawns());
const agentName = request.agent?.trim() || spawnPolicy.defaultAgent;
const planMode = request.session.getPlanModeState?.()?.enabled === true;View on GitHub (pinned to 9690622007)
Solutions
- Request one of the agents listed in the error's `Allowed:` text
- Reconfigure the session's spawn policy (getSessionSpawns / session spawn settings) to include the desired agent
- Enable session spawning if `spawnPolicy.enabled` is false
Example fix
// before
await task({ agent: "explorer" }); // not allowed
// after
await task({ agent: "researcher" }); // in allowedAgents Defensive patterns
Strategy: validation
Validate before calling
const policy = resolveSpawnPolicy(session.getSessionSpawns());
if (!policy.enabled || (policy.allowedAgents !== null && !policy.allowedAgents.includes(agentName))) {
throw new Error(`Agent "${agentName}" not permitted; allowed: ${policy.allowedErrorText}`);
}
await task({ agent: agentName }); Try / catch
try {
await task(req);
} catch (e) {
if (e instanceof StructuredSubagentError && e.message.includes("Allowed:")) {
const allowed = e.message.split("Allowed:")[1].trim();
return task({ ...req, agent: allowed.split(", ")[0] });
}
throw e;
} Prevention
- Check the session's spawn allowlist before composing agent names in prompts
- Keep allowlists and prompt templates in sync
- Avoid narrowing allowedAgents unless the child workflow is fully known
When it happens
Trigger: Calling the task tool with an agentName not in the session's spawn allowlist, or when session spawns are disabled entirely (`spawnPolicy.enabled === false`).
Common situations: A restricted/embedded session configured with a limited set of spawnable agents; typo in the agent name relative to the allowlist; session spawned with `allowedAgents` narrowed by a parent tool call and the child requesting something outside it.
Related errors
- {}: {error}
- inter-device move failed: {} to {}; unable to remove target:
- Permission denied
- cannot stat {file}: {error}
- failed to read filter definition {}: {e}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/633381c22abfa7ac.
Report an issue: GitHub.