conductor-oss/conductor · error · IllegalArgumentException

Unknown termination type in composite: ${type}

Error message

Unknown termination type in composite: ${type}

What it means

Thrown by buildSubConditionBody() when iterating sub-conditions inside a composite termination ('and'/'or') and encountering a sub-condition whose type is not one of the six supported values. This is the same validation as error 33 but applied to each entry in a composite's conditions list.

Source

Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/TerminationCompiler.java:318

    /**
     * Build the inline JavaScript body for a single sub-condition within a composite. Each
     * sub-condition evaluates to a local variable {@code rN} containing {@code {should_continue,
     * reason}}.
     */
    private static String buildSubConditionBody(TerminationConfig sub, int index) {
        String varName = "r" + index;
        String type = sub.getType();

        return switch (type) {
            case "text_mention" -> buildInlineTextMention(sub, varName);
            case "stop_message" -> buildInlineStopMessage(sub, varName);
            case "max_message" -> buildInlineMaxMessage(sub, varName);
            case "token_usage" -> buildInlineTokenUsage(sub, varName);
            case "and" -> buildInlineComposite(sub, varName, true, index);
            case "or" -> buildInlineComposite(sub, varName, false, index);
            default ->
                    throw new IllegalArgumentException(
                            "Unknown termination type in composite: " + type);
        };
    }

    private static String buildInlineTextMention(TerminationConfig config, String varName) {
        String textJs = JavaScriptBuilder.toJson(config.getText());
        boolean caseSensitive =
                config.getCaseSensitive() != null ? config.getCaseSensitive() : true;

        return "  var "
                + varName
                + " = (function() {"
                + "    var content = String($.result || '');"
                + "    var text = "
                + textJs
                + ";"
                + "    var caseSensitive = "
                + caseSensitive

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect each sub-condition in the composite's conditions list and verify its type is one of: text_mention, stop_message, max_message, token_usage, and, or.
  2. Check for null type values in sub-conditions.
  3. Fix the specific sub-condition whose type is invalid.

Example fix

// before: sub-condition has typo "token" instead of "token_usage"
TerminationConfig.builder()
    .type("or")
    .conditions(List.of(
        TerminationConfig.builder().type("max_message").maxMessages(10).build(),
        TerminationConfig.builder().type("token").maxTotalTokens(5000).build()))  // typo!
    .build();
// after
TerminationConfig.builder()
    .type("or")
    .conditions(List.of(
        TerminationConfig.builder().type("max_message").maxMessages(10).build(),
        TerminationConfig.builder().type("token_usage").maxTotalTokens(5000).build()))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> VALID_TERM_TYPES =
    Set.of("text_mention", "stop_message", "max_message", "token_usage", "and", "or");

void validateSubConditions(TerminationConfig composite) {
    if (composite.getConditions() == null) return;
    for (int i = 0; i < composite.getConditions().size(); i++) {
        TerminationConfig sub = composite.getConditions().get(i);
        if (sub.getType() == null || !VALID_TERM_TYPES.contains(sub.getType())) {
            throw new IllegalArgumentException(
                "conditions[" + i + "] has unknown type: " + sub.getType());
        }
    }
}

Type guard

static boolean allSubConditionsValid(TerminationConfig composite) {
    if (!Set.of("and", "or").contains(composite.getType())) return true;
    if (composite.getConditions() == null) return false;
    return composite.getConditions().stream().allMatch(
        c -> VALID_TERM_TYPES.contains(c.getType()));
}

Try / catch

try {
    String script = TerminationCompiler.buildTerminationScript(compositeConfig);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Unknown termination type in composite")) {
        // find and fix the sub-condition with the bad type
    }
    throw e;
}

Prevention

When it happens

Trigger: A composite TerminationConfig (type='and' or 'or') whose conditions list contains at least one TerminationConfig with a null or unrecognized type string.

Common situations: One sub-condition in a composite has a typo in its type (e.g., 'token' instead of 'token_usage'), or a sub-condition was added with a null type. This is harder to spot because the error surfaces only when the composite is compiled, not when each sub-condition is defined.

Related errors


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