{"record":{"id":"e42aeba35314b242","repo":"conductor-oss/conductor","slug":"plan-execute-config-getname-tool-t-getn","errorCode":null,"errorMessage":"PLAN_EXECUTE '${config.getName()}': tool '${t.getName()}' failed to serialise for PAC (${e.getMessage()}). The tool has ${guardrailCount} guardrail(s) — silently dropping it would compile a wrapper-less version of a safety-checked tool. Fix the ToolConfig (typically a non-Jackson-friendly value in inputSchema or config) and recompile.","messagePattern":"PLAN_EXECUTE '(.+?)': tool '(.+?)' failed to serialise for PAC \\((.+?)\\)\\. The tool has (.+?) guardrail\\(s\\) — silently dropping it would compile a wrapper-less version of a safety-checked tool\\. Fix the ToolConfig \\(typically a non-Jackson-friendly value in inputSchema or config\\) and recompile\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":500,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java","lineNumber":2639,"sourceCode":"            }\n            try {\n                @SuppressWarnings(\"unchecked\")\n                Map<String, Object> m = MAPPER.convertValue(t, Map.class);\n                parentToolsAsMaps.add(m);\n            } catch (Exception e) {\n                // /dg #7: fail-closed on ALL serialization failures, not just\n                // guardrailed ones. Previously a non-guardrailed tool was\n                // silently dropped from parentToolsByName with only a WARN,\n                // which meant ``knownToolNames`` still allowed the tool but\n                // PAC had no schema / inputSchema / guardrail context — a\n                // generate-op output landed in a bare SIMPLE with no\n                // validation. Treat the divergence as a compile error so the\n                // user fixes the ToolConfig (typically a non-Jackson-friendly\n                // value in inputSchema or config) instead of shipping a\n                // half-configured tool. Guardrailed tools get the longer\n                // diagnostic since the failure mode there is more dangerous.\n                int guardrailCount = t.getGuardrails() != null ? t.getGuardrails().size() : 0;\n                throw new IllegalStateException(\n                        \"PLAN_EXECUTE '\"\n                                + config.getName()\n                                + \"': tool '\"\n                                + t.getName()\n                                + \"' failed to serialise for PAC (\"\n                                + e.getMessage()\n                                + \").\"\n                                + (guardrailCount > 0\n                                        ? \" The tool has \"\n                                                + guardrailCount\n                                                + \" guardrail(s) — silently dropping it would compile a\"\n                                                + \" wrapper-less version of a safety-checked tool.\"\n                                        : \" Silently dropping the tool would leave\"\n                                                + \" ``knownToolNames`` allowing it while PAC has no schema or\"\n                                                + \" inputSchema for validation.\")\n                                + \" Fix the ToolConfig (typically a non-Jackson-friendly value\"\n                                + \" in inputSchema or config) and recompile.\",\n                        e);","sourceCodeStart":2621,"sourceCodeEnd":2657,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/compiler/MultiAgentCompiler.java#L2621-L2657","documentation":"Thrown as IllegalStateException when a PLAN_EXECUTE tool's ToolConfig cannot be serialized to a Map via Jackson's ObjectMapper.convertValue(). The compiler fail-closes on ALL serialization failures (not just guardrailed tools) because silently dropping a tool would leave PAC (Plan-Adaptive Compilation) without schema/guardrail context while knownToolNames still allowed it — a safety gap. The error message includes the tool name, the Jackson exception message, and the guardrail count.","triggerScenarios":"A PLAN_EXECUTE-strategy agent whose tool list contains a ToolConfig that Jackson cannot serialize to Map<String,Object>. Typically caused by a non-Jackson-friendly value in inputSchema or config — e.g., a raw Java class reference, a non-serializable object, a circular reference, or a custom type without a Jackson serializer.","commonSituations":"Putting non-JSON-serializable Java objects into ToolConfig.config or inputSchema (e.g., a Pattern object instead of a regex string, a Class<?> reference, or a deeply nested Map with non-String keys). Also happens when ToolConfig is constructed programmatically with values that can't round-trip through Jackson.","solutions":["Inspect the Jackson exception message embedded in the error — it names the field or type that failed serialization.","Ensure all values in ToolConfig.config and inputSchema are JSON-serializable (Strings, Numbers, Booleans, Lists, Maps with String keys).","Replace Pattern objects with regex strings, Class references with class name strings.","Check for circular references in nested config objects."],"exampleFix":"// before: non-serializable Pattern in inputSchema\nToolConfig.builder()\n    .name(\"validate\")\n    .inputSchema(Map.of(\"pattern\", Pattern.compile(\"^\\\\d+$\")))  // Pattern is not Jackson-serializable\n    .build();\n// after: use the regex string\nToolConfig.builder()\n    .name(\"validate\")\n    .inputSchema(Map.of(\"pattern\", \"^\\\\\\\\d+$\"))\n    .build();","handlingStrategy":"try-catch","validationCode":"// Pre-serialize each tool to catch failures before compile\nprivate static final ObjectMapper MAPPER = new ObjectMapper();\n\nvoid preSerializeTools(List<ToolConfig> tools) {\n    for (ToolConfig t : tools) {\n        try {\n            MAPPER.convertValue(t, Map.class);\n        } catch (Exception e) {\n            throw new IllegalStateException(\n                \"Tool '\" + t.getName() + \"' will fail PAC serialization: \" + e.getMessage(), e);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    compiler.compile(agentConfig);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"failed to serialise for PAC\")) {\n        // fix the non-Jackson-friendly value in the tool config\n    }\n    throw e;\n}","preventionTips":["Never put non-JSON types (Pattern, Class, File, etc.) in ToolConfig fields.","Pre-serialize tool configs with ObjectMapper.convertValue() in a test to catch issues early.","All Map keys must be Strings; all values must be primitives, Strings, Lists, or nested Maps."],"tags":["plan-execute","serialization","jackson","tool-config","agentspan","fail-closed"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}