conductor-oss/conductor · error · SafeConditionParseException
null condition
Error message
null condition
What it means
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.
Source
Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/util/SafeConditionInterpreter.java:78
* <li>{@code constructor}, {@code __proto__}, {@code Function}, {@code eval}.
* </ul>
*
* <p>If those ever need to be supported, extending the grammar requires adding a new node type with
* a {@link Node#eval(Map)} implementation — the addition is auditable in code review rather than
* silently re-opened by widening a regex.
*/
public final class SafeConditionInterpreter {
private SafeConditionInterpreter() {}
/** Maximum source length accepted by the parser. */
public static final int MAX_LENGTH = 1024;
// ── Public API ─────────────────────────────────────────────────
/** Parse a condition into an AST. Throws on syntax errors. */
public static Node parse(String src) {
if (src == null) throw new SafeConditionParseException("null condition");
if (src.length() > MAX_LENGTH) {
throw new SafeConditionParseException(
"condition exceeds " + MAX_LENGTH + " characters");
}
Parser p = new Parser(src);
Node ast = p.parseExpr();
p.expectEnd();
return ast;
}
/** Evaluate the parsed condition against a root map. */
public static boolean evaluate(String src, Map<String, Object> root) {
return truthy(parse(src).eval(root != null ? root : Map.of()));
}
/** True if and only if {@link #parse(String)} would accept this string. */
public static boolean isSafe(String src) {
try {View on GitHub (pinned to cf7c3e4a8a)
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.
Example fix
// before boolean ok = SafeConditionInterpreter.parse(condition).eval(root); // condition == null // after boolean ok = condition == null || SafeConditionInterpreter.evaluate(condition, root);
Defensive patterns
Strategy: validation
Validate before calling
if (condition == null) {
// no condition supplied -> treat as pass / skip
return true;
}
return SafeConditionInterpreter.evaluate(condition, root); Type guard
boolean isParsableCondition(String s) {
return s != null && s.length() <= SafeConditionInterpreter.MAX_LENGTH;
} Try / catch
try {
return SafeConditionInterpreter.evaluate(condition, root);
} catch (SafeConditionParseException e) {
// null condition is a plan/ingest bug; fail the step with a clear message
throw new IllegalArgumentException("invalid success_condition: " + e.getMessage(), e);
} Prevention
- Null-check success_condition before parsing.
- Default unset conditions to `true` at ingest.
- Validate the plan payload schema (condition is non-null when required).
When it happens
Trigger: Calling SafeConditionInterpreter.parse(null) or evaluate(null, root). A workflow/plan supplies a null success_condition that reaches the parser without a null guard.
Common situations: 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.
Related errors
- condition exceeds 1024 characters
- {location}: uses unsupported JSON Schema keyword '{key}' at
- {location}: unknown JSON Schema keyword '{key}' at {path}. A
- SWARM handoff type must be on_tool_result, on_text_mention,
- SWARM handoff target must name a swarm agent: ${handoff.getT
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/f9ea1a9d818e4424.
Report an issue: GitHub.