{"record":{"id":"f9ea1a9d818e4424","repo":"conductor-oss/conductor","slug":"null-condition","errorCode":null,"errorMessage":"null condition","messagePattern":"null condition","errorType":"validation","errorClass":"SafeConditionParseException","httpStatus":null,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/util/SafeConditionInterpreter.java","lineNumber":78,"sourceCode":" *   <li>{@code constructor}, {@code __proto__}, {@code Function}, {@code eval}.\n * </ul>\n *\n * <p>If those ever need to be supported, extending the grammar requires adding a new node type with\n * a {@link Node#eval(Map)} implementation — the addition is auditable in code review rather than\n * silently re-opened by widening a regex.\n */\npublic final class SafeConditionInterpreter {\n\n    private SafeConditionInterpreter() {}\n\n    /** Maximum source length accepted by the parser. */\n    public static final int MAX_LENGTH = 1024;\n\n    // ── Public API ─────────────────────────────────────────────────\n\n    /** Parse a condition into an AST. Throws on syntax errors. */\n    public static Node parse(String src) {\n        if (src == null) throw new SafeConditionParseException(\"null condition\");\n        if (src.length() > MAX_LENGTH) {\n            throw new SafeConditionParseException(\n                    \"condition exceeds \" + MAX_LENGTH + \" characters\");\n        }\n        Parser p = new Parser(src);\n        Node ast = p.parseExpr();\n        p.expectEnd();\n        return ast;\n    }\n\n    /** Evaluate the parsed condition against a root map. */\n    public static boolean evaluate(String src, Map<String, Object> root) {\n        return truthy(parse(src).eval(root != null ? root : Map.of()));\n    }\n\n    /** True if and only if {@link #parse(String)} would accept this string. */\n    public static boolean isSafe(String src) {\n        try {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/util/SafeConditionInterpreter.java#L60-L96","documentation":"SafeConditionInterpreter.parse throws SafeConditionParseException when the supplied condition expression is null. The interpreter is a hand-written recursive-descent parser/evaluator for plan-supplied `success_condition` strings; a null input has no grammar to parse and is rejected up front rather than NPE-ing inside the lexer.","triggerScenarios":"Calling SafeConditionInterpreter.parse(null) or evaluate(null, root). A workflow/plan supplies a null success_condition that reaches the parser without a null guard.","commonSituations":"A plan step omits success_condition entirely and the caller does not skip the parse; a JSON deserialization yields null for an unset field; a default value was not applied.","solutions":["Null-check before calling parse: treat null as \"no condition\" and skip evaluation.","Default the success_condition field to a literal like `true` when unset.","Validate the plan payload at ingest time and reject missing required conditions."],"exampleFix":"// before\nboolean ok = SafeConditionInterpreter.parse(condition).eval(root);  // condition == null\n// after\nboolean ok = condition == null || SafeConditionInterpreter.evaluate(condition, root);","handlingStrategy":"validation","validationCode":"if (condition == null) {\n    // no condition supplied -> treat as pass / skip\n    return true;\n}\nreturn SafeConditionInterpreter.evaluate(condition, root);","typeGuard":"boolean isParsableCondition(String s) {\n    return s != null && s.length() <= SafeConditionInterpreter.MAX_LENGTH;\n}","tryCatchPattern":"try {\n    return SafeConditionInterpreter.evaluate(condition, root);\n} catch (SafeConditionParseException e) {\n    // null condition is a plan/ingest bug; fail the step with a clear message\n    throw new IllegalArgumentException(\"invalid success_condition: \" + e.getMessage(), e);\n}","preventionTips":["Null-check success_condition before parsing.","Default unset conditions to `true` at ingest.","Validate the plan payload schema (condition is non-null when required)."],"tags":["agentspan","condition-interpreter","null-check","validation"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}