Code Node Output Validation#
Overview#
Code Node output validation in Dify enforces that values returned by sandboxed user code match the declared output schema. Validation runs after code execution, against the outputs map declared in CodeNodeData. It is strict: no implicit type coercion is performed. If a Python function returns an int for an output declared as string, the node fails immediately.
The implementation lives in the external graphon package (β₯ v0.5.2), which Dify instantiates via DifyNodeFactory. The validation entry point is CodeNode._transform_result(), called by CodeNode._run().
Execution & Response Parsing#
Before validation, the code runs in dify-sandbox (a seccomp-isolated Go process). Inputs are JSON-serialized and base64-encoded by TemplateTransformer.serialize_inputs(), and the sandbox wraps its return value between <<RESULT>> tags. TemplateTransformer.transform_response() extracts and JSON-parses that response, then:
- Requires the result to be a
dictwith all-string keys - Post-processes scientific-notation strings back into
float(e.g.-8.0E-5β-8e-05)
Declared Output Types#
Outputs are declared as CodeNodeData.Output objects keyed by variable name. Supported SegmentType values :
| Type | Description |
|---|---|
STRING | Plain string β no coercion from numeric/bool |
NUMBER | int or float |
BOOLEAN | bool |
OBJECT | Dict / mapping; supports nested children schema |
ARRAY_STRING | List of strings |
ARRAY_NUMBER | List of numbers |
ARRAY_BOOLEAN | List of booleans |
ARRAY_OBJECT | List of dicts |
For OBJECT outputs, children can be nested recursively, up to CODE_MAX_DEPTH levels (default: 5) . Exceeding the depth limit raises DepthLimitError .
Strict Type Enforcement#
No implicit coercion is applied. The per-type check methods (_check_string, _check_number, _check_boolean) accept only exact Python types :
_check_string(value, name)β passes onlystr(orNone); strips null bytes (\x00) but does not callstr()on non-string values_check_number(value, name)β passesintorfloat; does not coerce string representations_check_boolean(value, name)β passesboolonly
The practical consequence: if your code returns {"result": 42} but the declared output type is string, the node fails with "Output result must be a string, got int instead." .
The integration test test_execute_code_output_validator specifically covers this case. The deeper test_execute_code_output_validator_depth also tests:
- Type mismatches in nested objects and arrays (
number_validator: "1"againstnumbertype) - Strings exceeding
CODE_MAX_STRING_LENGTH(default: 400,000 chars) - Arrays exceeding length limits
Size & Depth Limits#
All limits are configured via CodeExecutionSandboxConfig and passed into CodeNodeLimits by DifyNodeFactory :
| Limit | Config Key | Default |
|---|---|---|
| Max string length | CODE_MAX_STRING_LENGTH | 400,000 chars |
| Max nesting depth | CODE_MAX_DEPTH | 5 |
| Max float precision | CODE_MAX_PRECISION | 20 decimal places |
| Max integer | CODE_MAX_NUMBER | 9,223,372,036,854,775,807 |
| Min integer | CODE_MIN_NUMBER | β9,223,372,036,854,775,807 |
| Max string array length | CODE_MAX_STRING_ARRAY_LENGTH | 30 |
| Max object array length | CODE_MAX_OBJECT_ARRAY_LENGTH | 30 |
| Max number array length | CODE_MAX_NUMBER_ARRAY_LENGTH | 1,000 |
These are overridable via environment variables.
Exception Hierarchy#
All output validation errors are ValueError subclasses :
ValueError
βββ CodeNodeError (graphon.nodes.code.exc)
βββ OutputValidationError β type mismatch / limit exceeded
βββ DepthLimitError β nested structure exceeds max_depth
The CodeNode._run() method catches these and maps them to WorkflowNodeExecutionStatus.FAILED with the error message surfaced on NodeRunResult.error .
Agent Node Contrast#
The Agent v2 node has a separate output checker (PerOutputTypeChecker) that handles required vs. optional presence semantics (outputs missing from the backend payload are flagged as NOT_PRODUCED vs. TYPE_CHECK_FAILED). The Code node's graphon validation does not have a separate "optional" concept β an output key present in outputs must appear in the returned dict unless the type check allows None.
Key Source Files#
| File | Purpose |
|---|---|
api/core/workflow/node_factory.py | Builds CodeNodeLimits from dify_config |
api/configs/feature/__init__.py | Defines all CODE_* limit defaults |
api/core/helper/code_executor/template_transformer.py | Serializes inputs; parses and validates sandbox response |
api/tests/integration_tests/workflow/nodes/test_code.py | Integration tests for type mismatch, depth, length, and scientific notation |
api/tests/unit_tests/core/workflow/nodes/code/code_node_spec.py | Unit tests for _check_* methods, exceptions, and CodeNodeData schemas |
api/core/workflow/nodes/agent_v2/output_type_checker.py | Agent v2 output checker (separate, for comparison) |