What is checked before a flow is published
The checks of the graph and of the settings of each node, which of them stop a publication, and the message the builder shows for each.
Validate and Publish check the draft of a flow before it can run. Each problem the check finds is tied to a node or to the whole graph, and the builder shows it on the node and at the top of the node's panel. This page lists every check with the message the builder shows for it.
Two kinds of check
A check of the graph is about the shape of the flow: one entry node, connected ports, no cycles, the models and pools a node names. Each has a code of its own.
A check of a node's settings is about the configuration of one node: a delay that is too long, a path that reads nothing. All of them come under one code of the graph,
invalid_node_config, and say which check failed.
What stops a publication
A problem is an error or a warning. An error stops the publication: nothing is published until it is fixed. A warning does not: it says that the flow will work otherwise than you may expect — a model node without an error branch, a pool with no connection that can serve the model.
Over the API the same list is error.details.issues of a publish refused with 422 and the code flow_invalid — Publish, versions and rollback. A rollback checks again only the models and pools of the version.
The checks of the graph
In the API an entry of issues carries such a code in code, and severity tells whether it stops a publish: an error does, a warning does not.
| Code | Level | Message in the builder |
|---|---|---|
invalid_graph_shape | error | The graph holds a value of the wrong type at {path}: {expected} is expected there. |
duplicate_node_key | error | The key “{node}” is used by more than one node. |
invalid_node_key | error | The key “{node}” must be 1 to {max} characters: lowercase Latin letters, digits, underscores and hyphens. |
unknown_node_type | error | “{node}” has an unknown type ({type}). |
node_type_not_supported | error | The type {type} of “{node}” cannot be published yet. |
node_type_frozen | error | The type {type} of “{node}” is frozen: flows published with it keep running, but a new version cannot hold it. Remove the node to publish. |
no_entry_node | error | The flow has no entry node to start from. |
multiple_entry_nodes | error | A flow may have only one entry node — “{node}” is one of several. |
unknown_edge_source | error | A connection starts at “{node}”, which does not exist. |
unknown_edge_target | error | A connection from “{node}” points at “{target}”, which does not exist. |
unknown_port | error | “{node}” has no “{port}” branch. |
duplicate_port_edge | error | The “{port}” branch of “{node}” has more than one connection. |
port_not_connected | error | The “{port}” branch of “{node}” leads nowhere. |
error_port_not_connected | warning | “{node}” has no error branch — a provider error will fail the whole operation. |
deny_port_not_connected | warning | “{node}” has no deny branch — a refusal will answer the caller with 402 or 403 instead of following a branch. |
cycle_detected | error | A connection loops back to “{node}” — a flow has to run forward. |
unreachable_node | warning | “{node}” cannot be reached from the entry node. |
path_without_terminal | error | The path through “{node}” ends without an answer or a rejection. |
invalid_node_config | error | “{node}” is not configured correctly. |
unknown_model | error | The model {model} of “{node}” is not in the catalogue. |
unknown_pool | error | The pool of “{node}” does not exist. |
pool_provider_mismatch | error | The pool of “{node}” serves {serves}, but the model needs {needs}. |
pool_without_connections | warning | The pool of “{node}” has no enabled connection. |
pool_cannot_serve_model | warning | No enabled connection in the pool of “{node}” can serve {model} — every call will fail until one can. |
pool_disabled | warning | The pool of “{node}” is disabled — every call will fail until it is enabled. |
park_inside_finance_chain | error | “{node}” reserves budget but waits before its model runs — a waiting run holds no reservation. |
misplaced_finance_node | error | “{node}” ({type}) is not part of a valid estimate → check → reserve → model → capture chain. |
ambiguous_finance_chain | error | “{node}” ({type}) leads to more than one model — an estimate, a check or a reserve belongs to the path of exactly one model call. |
cache_write_without_lookup | warning | “{node}” has no Cache Lookup above it, so it will store nothing. |
node_type_frozenrefuses Http Request, which is frozen unless the service is set up otherwise. A version published with it goes on running — Http Request.misplaced_finance_node,ambiguous_finance_chainandpark_inside_finance_chainare about the money chain: the nodes that stand around a call of AI Model. The money chain says what each of them asks.cache_write_without_lookupis a warning: a Cache Write with no Cache Lookup above it stores nothing.
The checks of a node's settings
In the API an entry of issues names such a check in params.detail; its code is invalid_node_config.
| Check | Message in the builder |
|---|---|
queue_invalid_delay | The delay of “{node}” must be a whole number of seconds, at least 1. |
queue_delay_too_long | The delay of “{node}” is longer than a waiting execution is kept: at most {max} seconds. |
require_approval_invalid_expires_hours | The decision window of “{node}” must be a whole number of hours, at least 1. |
require_approval_expires_too_late | The decision window of “{node}” is longer than a waiting execution is kept: at most {max} hours. |
cache_unsupported_scope | “{node}” uses a cache scope that does not exist. |
cache_key_fields_not_list | The key fields of “{node}” must be a list of input paths. |
cache_key_fields_empty_entry | One of the key fields of “{node}” is empty. |
cache_key_fields_rooted_path | “{node}” keys the cache by “{path}”, but key fields are read inside the input only: a path there does not start with “{root}”. |
cache_key_fields_padded_path | “{node}” keys the cache by “{path}”, which has spaces at its ends: key fields are read exactly as written. |
cache_invalid_ttl | The lifetime of “{node}” must be a whole number of seconds, at least 1. |
ai_model_needs_model | “{node}” needs a model. |
ai_model_invalid_pool_id | The pool of “{node}” must be named by its id, written as text. |
ai_model_invalid_max_output_tokens | The output-token ceiling of “{node}” must be a whole number, at least 1. |
ai_model_invalid_max_attempts | The attempt limit of “{node}” must be a whole number from 1 to {max}. |
ai_model_invalid_temperature | The temperature of “{node}” must be a number between {min} and {max}. |
ai_model_unsupported_on_rate_limit | “{node}” uses a rate-limit behaviour that does not exist. |
ai_model_unsupported_on_provider_error | “{node}” uses a provider-error behaviour that does not exist. |
ai_model_tools_not_list | The tools of “{node}” must be a non-empty list. |
ai_model_unusable_tool | “{node}” has a tool that is neither a named function nor a typed provider tool. |
ai_model_invalid_response_format | The response format of “{node}” must be an object with a type. |
ai_model_unsupported_on_overrun | “{node}” uses an overrun policy that does not exist. |
ai_model_invalid_overrun_tolerance | The overrun tolerance of “{node}” must be between {min} and {max}. |
ai_model_needs_degrade_model | “{node}” degrades on overrun but names no model to degrade to. |
ai_model_degrades_to_same_model | “{node}” degrades to the model it already uses. |
condition_needs_field | “{node}” needs a field to test. |
condition_field_bad_path | “{node}” tests “{path}”, which is not a path into input, context or nodes. |
condition_field_unknown_node | “{node}” tests “{path}”, but the flow has no node “{ref}”. |
condition_field_later_node | “{node}” tests “{path}”, but “{ref}” does not run before it — its output does not exist yet there. |
condition_unsupported_operator | “{node}” uses an operator that does not exist. |
condition_needs_value | “{node}” needs a value to compare against. |
condition_value_not_number | The value of “{node}” must be a number: its operator ({operator}) compares numbers. |
condition_value_not_list | The value of “{node}” must be a non-empty list: its operator checks that the field is one of the listed values. |
reject_needs_error_code | “{node}” needs an error code. |
reject_invalid_error_code | The error code of “{node}” must be 1 to {max} characters: lowercase Latin letters, digits, dots and underscores. |
reject_invalid_message | The message of “{node}” must be text of at most {max} characters. |
return_unsupported_source | “{node}” answers with a source that does not exist. |
return_literal_not_object | “{node}” answers with a fixed value, and that value must be an object. |
return_needs_node | “{node}” answers with the output of a node and has to name another node of the flow. |
return_unknown_node | “{node}” answers with the output of “{ref}”, but the flow has no node “{ref}”. |
return_terminal_node | “{node}” answers with the output of “{ref}”, but “{ref}” ends the flow itself and never runs before this answer. Name a node that runs earlier. |
log_unsupported_level | “{node}” uses a level that does not exist. |
log_invalid_message | The message of “{node}” must be text of at most {max} characters. |
transform_needs_field | “{node}” needs at least one field to build. |
transform_too_many_fields | “{node}” builds more than {max} fields. |
transform_field_not_object | “{node}” has a field that is not an object. |
transform_field_without_name | “{node}” has a field without a usable name: a Latin letter or an underscore first, then letters, digits and underscores, 64 characters at most. |
transform_field_both_sources | The field “{field}” of “{node}” has both a path and a fixed value. |
transform_field_without_source | The field “{field}” of “{node}” needs either a path or a fixed value. |
transform_field_bad_path | The field “{field}” of “{node}” reads “{path}”, which is not a path into input, context or nodes. |
transform_field_repeated | “{node}” builds the field “{field}” more than once. |
transform_field_unknown_node | The field “{field}” of “{node}” reads “{path}”, but the flow has no node “{ref}”. |
transform_field_later_node | The field “{field}” of “{node}” reads “{path}”, but “{ref}” does not run before it. |
budget_check_unsupported_mode | “{node}” uses a budget mode that does not exist. |
budget_check_unsupported_window | “{node}” uses a budget window that does not exist. |
budget_check_invalid_default_limit | The default limit of “{node}” is not a valid amount. |
budget_check_allocations_not_list | The allocations of “{node}” must be a list. |
budget_check_needs_allocation | “{node}” needs at least one allocation or a default limit. |
budget_check_allocation_not_object | “{node}” has an allocation that is not an object. |
budget_check_allocation_without_model | “{node}” has an allocation with no model chosen. |
budget_check_duplicate_model | “{node}” allocates to {model} twice. |
budget_check_invalid_limit | The limit for {model} on “{node}” is not a valid amount. |
budget_check_unknown_model | The model {model} is not in the catalogue. |
http_needs_url | “{node}” needs a url. |
http_templated_host | “{node}” may not template its host. |
http_egress_not_configured | “{node}” cannot call out: no outbound host is configured. |
http_host_not_allowed | The url of “{node}” is not on the outbound allowlist (allowed: {hosts}). |
http_scheme_not_https | “{node}” must call https. |
http_port_not_allowed | “{node}” may only call port 443. |
http_url_has_credentials | The url of “{node}” carries credentials. |
http_host_is_address_literal | “{node}” must call a host name, not an address. |
http_url_unparseable | The url of “{node}” cannot be read. |
http_url_bad_placeholder | The url of “{node}” has a placeholder that names no value in input, context or the output of a node — the call would fail on every run. |
http_url_unknown_node | The url of “{node}” reads “{path}”, but the flow has no node “{ref}”. |
http_url_later_node | The url of “{node}” reads “{path}”, but “{ref}” does not run before it. |
http_unsupported_method | “{node}” uses an unsupported method. |
http_headers_not_map | The headers of “{node}” must be a map of names to values. |
http_too_many_headers | “{node}” sets more than {max} headers. |
http_header_unusable_name | “{node}” has a header with an unusable name. |
http_header_forbidden | “{node}” may not set “{header}”: the graph is stored as plain text, so a credential here would not be a secret. |
http_header_needs_value | The header “{header}” of “{node}” needs a text value. |
http_invalid_timeout | “{node}” may wait between 1 and {max} seconds. |
http_invalid_max_bytes | “{node}” may read up to {max} bytes. |
http_invalid_body_from | The body path of “{node}” must point into the execution. |
http_body_from_unknown_node | The body of “{node}” is read from “{path}”, but the flow has no node “{ref}”. |
http_body_from_later_node | The body of “{node}” is read from “{path}”, but “{ref}” does not run before it. |
The article of each node lists the checks of its own settings under «Errors».
Where to go next
Flow builder — Validate, Publish and the panel of a node.
How a flow is built — what every flow must have.
Ports and branching — required ports and the warnings about the optional ones.
Execution context and paths — what a path in the settings of a node may read.
Built from openapi b070e1f, sdk contract 5cc7055, php ae4a53b, node 84bc62d