conductor-oss/conductor · error · IllegalStateException
${usx.message}
Error message
${usx.message} What it means
Thrown as IllegalStateException wrapping a SchemaSubsetValidator.UnsupportedSchemaException. The validator checks that a tool's inputSchema only uses JSON Schema keywords the runtime INLINE validator actually handles (a Draft-07 subset). Unsupported keywords like $ref, allOf, oneOf, format, etc. would silently pass at runtime, producing permissive validation. The message is forwarded verbatim from the validator.
Source
Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java:2619
List<Map<String, Object>> parentToolsAsMaps = new ArrayList<>();
for (ToolConfig t : parentTools) {
// /dg #1: reject schemas using JSON-Schema features the runtime
// INLINE validator silently ignores ($ref, allOf, anyOf, oneOf,
// format, if/then/else, etc.). Without this check users got
// permissive runtime validation — the schema appears to declare
// constraints but the validator never fires them. Fail at
// agent-compile time with the exact offending keyword + path.
if (t.getInputSchema() != null) {
try {
SchemaSubsetValidator.validate(
t.getInputSchema(),
"PLAN_EXECUTE '"
+ config.getName()
+ "': tool '"
+ t.getName()
+ "' inputSchema");
} catch (SchemaSubsetValidator.UnsupportedSchemaException usx) {
throw new IllegalStateException(usx.getMessage(), usx);
}
}
try {
@SuppressWarnings("unchecked")
Map<String, Object> m = MAPPER.convertValue(t, Map.class);
parentToolsAsMaps.add(m);
} catch (Exception e) {
// /dg #7: fail-closed on ALL serialization failures, not just
// guardrailed ones. Previously a non-guardrailed tool was
// silently dropped from parentToolsByName with only a WARN,
// which meant ``knownToolNames`` still allowed the tool but
// PAC had no schema / inputSchema / guardrail context — a
// generate-op output landed in a bare SIMPLE with no
// validation. Treat the divergence as a compile error so the
// user fixes the ToolConfig (typically a non-Jackson-friendly
// value in inputSchema or config) instead of shipping a
// half-configured tool. Guardrailed tools get the longer
// diagnostic since the failure mode there is more dangerous.View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Inline all $ref references — replace $ref pointers with their resolved schema objects directly.
- Replace format constraints (e.g., 'format': 'email') with explicit pattern regex or remove them.
- Flatten allOf/anyOf/oneOf compositions into a single object schema.
- Replace const with enum: [value].
- Remove patternProperties, readOnly, writeOnly, and other non-supported keywords.
Example fix
// before: inputSchema with $ref and format
{
"type": "object",
"properties": {
"email": {"type": "string", "format": "email"},
"user": {"$ref": "#/$defs/User"}
},
"$defs": {"User": {"type": "object", "properties": {"name": {"type": "string"}}}}
}
// after: inlined, format removed, $ref resolved
{
"type": "object",
"properties": {
"email": {"type": "string", "pattern": "^[^@]+@[^@]+\\.[^@]+$"},
"user": {"type": "object", "properties": {"name": {"type": "string"}}}
}
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate all tool input schemas before compiling
private static final Set<String> SUPPORTED = new LinkedHashSet<>(Arrays.asList(
"type", "properties", "required", "additionalProperties", "items",
"enum", "minLength", "maxLength", "pattern", "minimum", "maximum",
"minItems", "maxItems", "title", "description", "examples",
"default", "$schema", "$id"));
void preValidateSchemas(List<ToolConfig> tools) {
for (ToolConfig t : tools) {
if (t.getInputSchema() != null) {
SchemaSubsetValidator.validate(t.getInputSchema(),
"tool '" + t.getName() + "' inputSchema");
}
}
} Try / catch
try {
SchemaSubsetValidator.validate(tool.getInputSchema(), location);
} catch (SchemaSubsetValidator.UnsupportedSchemaException e) {
// rewrite the schema to use only supported keywords, then retry
log.warn("Schema rejected: {}", e.getMessage());
throw e;
} Prevention
- Run SchemaSubsetValidator.validate() in a unit test against every tool schema before deploying.
- Avoid $ref and $defs in tool schemas — inline everything.
- Pydantic-generated schemas commonly use $ref/allOf — flatten them before use.
- Do not use 'format' — replace with 'pattern' regex.
When it happens
Trigger: A PLAN_EXECUTE-strategy agent with a tool whose inputSchema (ToolConfig.getInputSchema()) contains an unsupported JSON Schema keyword. The supported set is: type, properties, required, additionalProperties, items, enum, minLength, maxLength, pattern, minimum, maximum, minItems, maxItems, title, description, examples, default, $schema, $id. Keywords like $ref, allOf, anyOf, oneOf, format, const, if/then/else, patternProperties, and others are rejected.
Common situations: Using a JSON Schema generated by Pydantic, FastAPI, or OpenAPI that includes $ref/$defs (very common with Pydantic v2), format constraints (e.g., 'format': 'date-time'), or allOf/anyOf composition. These are valid Draft-07 but the runtime validator ignores them silently, so the compiler rejects them at compile time.
Related errors
- PLAN_EXECUTE strategy requires ``planner=<Agent>`` on the pa
- PLAN_EXECUTE harness '${config.getName()}' has guardrails wi
- PLAN_EXECUTE '${config.getName()}': tool '${t.getName()}' fa
- plan_source must include a non-empty 'tool' field
- plan_source.tool '${toolName}' is not registered as a harnes
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/ad32c2b5921e3fd3.
Report an issue: GitHub.