conductor-oss/conductor · error · IllegalArgumentException

SWARM handoff target must name a swarm agent: ${handoff.getT

Error message

SWARM handoff target must name a swarm agent: ${handoff.getTarget()}

What it means

Thrown when a SWARM handoff's 'target' field is null or does not match any agent name in the swarm. The compiler builds a set of valid targets from the parent agent's name plus all sub-agent names (config.getName() + each agent in config.getAgents()), then checks each handoff's target against it.

Source

Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java:1493

    /** Validate the declarative SWARM contract without changing its wire representation. */
    private static void validateSwarmHandoffs(AgentConfig config) {
        if (config.getHandoffs() == null) return;
        Set<String> targets = new HashSet<>();
        targets.add(config.getName());
        if (config.getAgents() != null) {
            for (AgentConfig agent : config.getAgents()) targets.add(agent.getName());
        }
        for (HandoffConfig handoff : config.getHandoffs()) {
            if (handoff == null
                    || handoff.getType() == null
                    || !Set.of("on_tool_result", "on_text_mention", "on_condition")
                            .contains(handoff.getType())) {
                throw new IllegalArgumentException(
                        "SWARM handoff type must be on_tool_result, on_text_mention, or on_condition");
            }
            if (handoff.getTarget() == null || !targets.contains(handoff.getTarget())) {
                throw new IllegalArgumentException(
                        "SWARM handoff target must name a swarm agent: " + handoff.getTarget());
            }
            switch (handoff.getType()) {
                case "on_tool_result" -> {
                    if (isBlank(handoff.getToolName()) || isBlank(handoff.getResultContains())) {
                        throw new IllegalArgumentException(
                                "on_tool_result requires toolName and resultContains");
                    }
                }
                case "on_text_mention" -> {
                    if (isBlank(handoff.getText())) {
                        throw new IllegalArgumentException("on_text_mention requires text");
                    }
                }
                case "on_condition" -> {
                    if (isBlank(handoff.getTaskName())) {
                        throw new IllegalArgumentException(
                                "on_condition requires a nonblank taskName");

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Ensure the handoff's target exactly matches the 'name' field of the parent agent or one of its sub-agents (case-sensitive).
  2. Check for typos — the target must be an exact string match against an agent name in the swarm.
  3. If you renamed an agent, update all handoff targets that point to the old name.

Example fix

// before: agent named "research-writer" but target says "research_writer"
{"type": "on_text_mention", "text": "handoff", "target": "research_writer"}
// after
{"type": "on_text_mention", "text": "handoff", "target": "research-writer"}
Defensive patterns

Strategy: validation

Validate before calling

void validateHandoffTargets(AgentConfig config) {
    Set<String> validTargets = new HashSet<>();
    validTargets.add(config.getName());
    if (config.getAgents() != null) {
        for (AgentConfig a : config.getAgents()) validTargets.add(a.getName());
    }
    if (config.getHandoffs() != null) {
        for (HandoffConfig h : config.getHandoffs()) {
            if (h.getTarget() == null || !validTargets.contains(h.getTarget())) {
                throw new IllegalArgumentException(
                    "Handoff target '" + h.getTarget() + "' not in valid targets: " + validTargets);
            }
        }
    }
}

Try / catch

try {
    compiler.compile(agentConfig);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("handoff target must name a swarm agent")) {
        String badTarget = extractTargetFromMessage(e.getMessage());
        // cross-check against agent names and fix
    }
    throw e;
}

Prevention

When it happens

Trigger: A SWARM-strategy agent config where a HandoffConfig.target is null, has a typo, or references an agent name that doesn't exist in the swarm's agents list (including the parent agent's own name).

Common situations: Renaming a sub-agent but forgetting to update handoff targets, referencing a target by description instead of name, or a mismatch between the 'name' field and what 'target' points to. Also happens when the target uses different casing than the agent's declared name.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/f0f55a12d24551e8. Report an issue: GitHub.