docusealco/docuseal · error · Submitters::SubmitValues::ValidationError
Formula infinite loop
Error message
Formula infinite loop
What it means
Raised by Submitters::SubmitValues.normalize_formula. Formula fields can reference other fields via {{uuid}} placeholders; when a referenced field itself has a preferences.formula, its formula is expanded recursively. A depth counter guards the expansion: recursion deeper than 10 levels means the formula graph is cyclic (or chained beyond 10 formula fields), so the calculation is aborted with 'Formula infinite loop'.
Source
Thrown at lib/submitters/submit_values.rb:239
end
values = submission_values.merge(acc.compact_blank)
acc[field['uuid']] =
if field['type'] == 'text'
eval_text_formula_value(formula, values, submitter.submission)
else
normalized_formula = normalize_formula(formula, submitter.submission, submission_values:)
calculate_formula_value(normalized_formula, values)
end
end
computed_values.compact_blank
end
def normalize_formula(formula, submission, depth: 0, submission_values: nil)
raise ValidationError, 'Formula infinite loop' if depth > 10
formula.gsub(/{{(.*?)}}/) do |match|
uuid = Regexp.last_match(1)
if (nested_formula = submission.fields_uuid_index.dig(uuid, 'preferences', 'formula').presence)
if check_field_conditions(submission_values, submission.fields_uuid_index[uuid], submission.fields_uuid_index)
"(#{normalize_formula(nested_formula, submission, depth: depth + 1, submission_values:)})"
else
'0'
end
else
match
end
end
end
def calculate_formula_value(_formula, _values)
0View on GitHub (pinned to 004a22c1c8)
Solutions
- Open the template and remove the circular reference: a formula must not directly or indirectly reference its own field
- Flatten deep chains — reference plain number fields instead of stacking formula-on-formula more than 10 levels
- Audit every field's preferences.formula for {{uuid}} tokens that resolve to fields which themselves carry a formula
- If a two-way calculation is needed, split it into independent fields that read the same source fields
Example fix
# before (template field preferences)
# field A (formula): "{{B}} * 2"
# field B (formula): "{{A}} + 1" -> cycle: A -> B -> A
# after
# field A (formula): "{{qty}} * {{price}}"
# field B (formula): "{{qty}} * {{price}} + {{tax}}" (only non-formula references) Defensive patterns
Strategy: validation
Validate before calling
formulas = submission.template_fields.to_h { |f| [f['uuid'], f.dig('preferences', 'formula').to_s] }
refs = formulas.transform_values { |s| s.scan(/\{\{(\w+)\}\}/).flatten }
cyclic = formulas.keys.any? do |uuid|
stack = refs[uuid].dup
seen = [uuid]
until stack.empty?
u = stack.pop
next false if u == uuid || (seen.include?(u) && stack.empty? && u == uuid)
break true if u == uuid
seen << u if formulas.key?(u)
stack.concat(refs[u]) if formulas.key?(u) && !seen.include?(u)
end == true
end
# reject the template before any submission if cyclic Try / catch
begin
Submitters::SubmitValues.call(submitter, params, request)
rescue Submitters::SubmitValues::ValidationError => e
if e.message == 'Formula infinite loop'
Rollbar.warning("Cyclic formulas on submission #{submitter.submission_id}") if defined?(Rollbar)
end
raise
end Prevention
- Validate template formulas for cycles at template-save time, not at submission time
- Prefer referencing plain input fields in formulas; avoid formula referencing formula
- Add a template lint step in CI for imported/copied templates that scans {{uuid}} references
When it happens
Trigger: A template formula field whose {{uuid}} placeholder points to another formula field that (directly or via a chain) points back — e.g. A = '{{B}} * 2' and B = '{{A}} + 1', or A = '{{A}}' — or a chain of more than 10 formula fields. Raised on every submit that computes formula values (build_formula_values).
Common situations: A template author copies a formula into a field that field references; a default_value or formula is edited to self-reference after launch, so all subsequent submissions fail; long formula-on-formula chains legitimately exceed depth 10; multi-submitter templates where merged values create an indirect cycle.
Related errors
AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/2879aac520144672.
Report an issue: GitHub.